Oracle SQL数据修改
我有一张如下所示的表格:Oracle SQL数据修改,sql,oracle,Sql,Oracle,我有一张如下所示的表格: RowID | ID | col | Label | ----------------------------------- 1 | 1 | Bad | N | ----------------------------------- 2 | 1 | Very Good | N | <---| ----------------------------------- 3
RowID | ID | col | Label |
-----------------------------------
1 | 1 | Bad | N |
-----------------------------------
2 | 1 | Very Good | N | <---|
-----------------------------------
3 | 1 |Super Good | N | <---| Either Label to be 'Y' (Contain 'Good')
-----------------------------------
4 | 1 | Too Bad | Y | <---$ Need this one to be 'N' (Contain 'Bad')
-----------------------------------
5 | 2 | F*** Good | N |
-----------------------------------
6 | 2 | So Good | Y |
-----------------------------------
7 | 2 | Really Bad| Y | <---$ Need both to be 'N' (Contain 'Bad')
-----------------------------------
8 | 2 | Bad | Y | <---$
-----------------------------------
9 | 3 | Good | N |
-----------------------------------
10 | 3 | Good | Y |
-----------------------------------
11 | 3 | Bad Bad | N |
RowID | ID | col | Label |
-----------------------------------
1 | 1 |坏| N |
-----------------------------------
2 | 1 |非常好| N |我想这会得到你想要的结果:
select t.*,
case when col like '%Bad%' then 'N'
when max(case when col like '%Good%' then label else 'N' end)
over (partition by id) = 'Y'
then label
when row_number()
over (partition by id, case when col like '%Good%' then 'Y' end order by null) = 1
then 'Y'
else label
end as new_label
from your_table t
order by rn;
RN ID COL LABEL NEW_LABEL
---------- ---------- ---------- ----- ---------
1 1 Bad N N
2 1 Very Good N Y
3 1 Super Good N N
4 1 Too Bad Y N
5 2 F*** Good N N
6 2 So Good Y Y
7 2 Really Bad Y N
8 2 Bad Y N
9 3 Good N N
10 3 Good Y Y
11 3 Bad Bad N N
(我没有使用rn
,我只是将其作为虚拟列保留在中,用于对结果集进行排序)
这会为任何包含Bad的值选择“N”;否则它是一个好值,如果ID的任何好值已经是Y,那么该ID的所有好值的标志将被保留;否则,半随机良好值设置为Y
基于此更新/合并表将很困难,因为没有一个键可以关联,至少在您显示的内容中是如此,除非-可能-值在ID中是唯一的。或者您没有显示另一个键列
我确实有一个唯一的ID列(使用sys\u guid())
您可以在合并中使用该选项,并使第2行和第3行中的哪一行变得更加随意:
merge into your_table target
using (
select t.*,
case when col like '%Bad%' then 'N'
when max(case when col like '%Good%' then label else 'N' end)
over (partition by id) = 'Y' then label
when row_number()
over (partition by id, case when col like '%Good%' then 'Y' end
order by guid_col) = 1 then 'Y'
else label
end as new_label
from your_table t
) source on (source.guid_col = target.guid_col)
when matched then
update set target.label = source.new_label
where target.label is null or target.label != source.new_label
/
4 rows merged.
where
子句的作用是只更新标签实际更改的行,而不是更新表中的每一行
此外,如果这是在修改数据时必须定期重新计算的内容,则最好使用始终动态计算标签的视图;虽然你可以看到“Y”在一个ID内移动,但用这种方法是不会的。这个解决方案很棒,尽管我花了一些时间才弄清楚每个步骤的逻辑!谢谢是的,我确实有一个唯一的ID列(使用sys\u guid()
),我没有显示它,因为我认为它不会有帮助…@JeffXi-是的,查询不需要它,尽管您可以使用它而不是order by null
,以使它更受控制。不过,您可以将其用于合并,并且能够将其限制为只包含实际更改的标签,这将有助于处理大型表。这真的有助于我的大桌子的性能。再次感谢你!