oracle - 更新每组的第一行 - Oracle
问题描述
需要从其他表的数据中只更新一个表的每组的顶行。
我需要使用表 B 中的详细信息更新表 A
Table A
---------
ID Name Date PCNO
1 abc 1/1/12 123
2 def 1/1/12 234
3 fgh 1/2/12 222
4 asd 1/2/12 234
TABLE B
-----------
ID Name Date PCNO
1 adsf 1/1/12 4343
2 sdf 1/2/12 9347
对于按“日期”分组并按 PCNO desc 排序的表 A 的每个顶部记录,我想更新表 B 中的值。
我是否为此目的使用排名。
解决方案
您可以使用等级或密集等级(甚至行号)来识别“顶部”行,但您可能不需要考虑如果在您的真实数据中可能存在联系,该怎么办:
select a.id, a.name, a.date_col, a.pcno,
dense_rank() over (partition by date_col order by pcno desc) as rnk
from table_a a;
ID NAME DATE_COL PCNO RNK
---------- ---- ---------- ---------- ----------
2 def 2012-01-01 234 1
1 abc 2012-01-01 123 2
4 asd 2012-01-02 234 1
3 fgh 2012-01-02 222 2
您可以加入表 B 以获得排名靠前的新值:
select a.id, a.name, a.date_col, a.pcno,
dense_rank() over (partition by a.date_col order by a.pcno desc) as rnk,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.name else a.name end as new_name,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.pcno else a.pcno end as new_pcno
from table_a a
join table_b b on b.date_col = a.date_col;
ID NAME DATE_COL PCNO RNK NEW_ NEW_PCNO
---------- ---- ---------- ---------- ---------- ---- ----------
2 def 2012-01-01 234 1 adsf 4343
1 abc 2012-01-01 123 2 abc 123
4 asd 2012-01-02 234 1 sdf 9347
3 fgh 2012-01-02 222 2 fgh 222
然后您可以在合并语句中使用它:
merge into table_a target
using (
select a.id, a.name, a.date_col, a.pcno,
dense_rank() over (partition by a.date_col order by a.pcno desc) as rnk,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.name else a.name end as new_name,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.pcno else a.pcno end as new_pcno
from table_a a
join table_b b on b.date_col = a.date_col
) source
on (source.id = target.id)
when matched then update
set target.name = source.new_name, target.pcno = source.new_pcno
where source.rnk = 1;
或许
merge into table_a target
using (
select a.id, a.name, a.date_col, a.pcno,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.name else a.name end as new_name,
case when dense_rank() over (partition by a.date_col order by a.pcno desc) = 1
then b.pcno else a.pcno end as new_pcno
from table_a a
join table_b b on b.date_col = a.date_col
) source
on (source.id = target.id)
when matched then update
set target.name = source.new_name, target.pcno = source.new_pcno
where target.name != source.new_name or target.pcno != source.new_pcno;
其中任何一个报告2 rows merged
,然后:
select * from table_a;
ID NAME DATE_COL PCNO
---------- ---- ---------- ----------
1 abc 2012-01-01 123
2 adsf 2012-01-01 4343
3 fgh 2012-01-02 222
4 sdf 2012-01-02 9347
如果某个日期并不总是匹配,您可能需要对其进行调整,尽管内部连接应该负责这一点。
推荐阅读
- chart.js - ChartJs 折线图 - 在某些数据点上方显示永久图标,并在悬停时显示文本
- facebook - 使用名称和城市打开 Facebook 搜索结果的 URL
- python - VideoPlayer kivymd python
- java - Sphinx4 StreamSpeechRecognizer 实时
- flutter - 使用 PopupMenuButton 后背景模糊
- linux - 在 Bash 脚本中测试用户是否可以使用 `read` 或等效方法输入数据
- java - ClientHello 只传递一个可用的密码套件,导致握手错误
- date - 在 Julia 中,如何将 DateFormat 年份设置为 19 表示 2019?
- javafx - javafx.scene.Scene 无法转换为 javafx.scene.layout.Pane
- windows-10 - AppData 文件夹重定向手动注册表更改