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
,以使它更受控制。不过,您可以将其用于合并,并且能够将其限制为只包含实际更改的标签,这将有助于处理大型表。这真的有助于我的大桌子的性能。再次感谢你!