根据每个唯一标识符的条件更新值

Posted

技术标签:

【中文标题】根据每个唯一标识符的条件更新值【英文标题】:Update a value based on criteria for each Unique Identifier 【发布时间】:2020-02-04 18:23:46 【问题描述】:

我有一个查询,我想根据每个主键的特定条件更新一个值。例如,如果 TYPE 是“ASBESTOS”,并且此特定项目不存在 TYPE“CONTIN”,我想将“ASBESTOS”更改为“CONTIN”。

我已经通过下面的查询实现了这一点,但这会将整个群体的 ASBESTOS 值更新为 CONTIN,即使 CONTIN 已经存在,基本上也会导致重复值。如果 CONTIN 尚不存在,则应仅添加它。也许一个 Windows 函数可以工作,以便它查看每个单独的项目,但我得到一个语法错误。感谢您的帮助!

 SELECT PROJECT, 
 CASE WHEN TYPE = 'ASBESTOS' AND TYPE NOT IN 'CONTIN' THEN 'CONTIN' ELSE TYPE END AS TYPE, 
 SUM(OBLIGATION) AS OBS 
 FROM OBS_MASTER
 WHERE PROJECT = '074190'
 GROUP BY PROJECT, TYPE;

 Original:

 PROJECT      TYPE          OBS           
 074190      ASBESTOS     26326.99     
 074190        CM             0 

 Current Result:
 PROJECT      TYPE         OBS            
 074190        CM           0               
 074190      CONTIN      26326.99   

【问题讨论】:

您的查询没有更新任何内容。 【参考方案1】:

如果我理解正确,您可以使用窗口函数计算每个项目的“CONTIN”数量,然后将该信息用于聚合键:

SELECT PROJECT, 
       (CASE WHEN NUM_CONTIN = 0 AND TYPE = 'ASBESTOS' THEN 'CONTIN' ELSE TYPE
        END) as TYPE
       SUM(OBLIGATION) AS OBS 
FROM (SELECT om.*,
             SUM(CASE WHEN TYPE = 'CONTIN' THEN 1 ELSE 0 END) OVER (PARTITION BY PROJECT) as NUM_CONTIN
      FROM OBS_MASTER om
     ) om
WHERE PROJECT = '074190'
GROUP BY PROJECT,
         (CASE WHEN NUM_CONTIN = 0 AND TYPE = 'ASBESTOS' THEN 'CONTIN' ELSE TYPE
          END)

【讨论】:

【参考方案2】:

这是另一个选择:

SQL> with
  2  obs_master (project, type, obligation) as
  3    -- sample data
  4    (select 1, 'ASBESTOS', 2500 from dual union all
  5     select 1, 'CONTIN'  , 1500 from dual union all
  6     select 1, 'CM'      ,  500 from dual union all
  7     --
  8     select 2, 'ASBESTOS', 1000 from dual union all
  9     select 2, 'CM'      , 1000 from dual
 10    ),
 11  temp as
 12    -- check whether project has CONTIN type
 13    (select project, min(type) cb_contin
 14     from obs_master
 15     group by project, type
 16     having type = 'CONTIN'
 17    )
 18  select a.project,
 19         -- if type = ASBESTOS and that project doesn't contain CONTIN,
 20         -- replace ASBESTOS with CONTIN
 21         case when a.type = 'ASBESTOS' and
 22                   b.cb_contin <> 'CONTIN'
 23              then 'CONTIN'
 24              else a.type
 25         end type,
 26         sum(a.obligation) obs
 27  from obs_master a left join temp b on a.project = b.project
 28  group by a.project,
 29         case when a.type = 'ASBESTOS' and
 30                   b.cb_contin <> 'CONTIN'
 31              then 'CONTIN'
 32              else a.type
 33         end
 34  order by a.project;

   PROJECT TYPE            OBS
---------- -------- ----------
         1 ASBESTOS       2500
         1 CM              500
         1 CONTIN         1500
         2 ASBESTOS       1000
         2 CM             1000

SQL>

【讨论】:

【参考方案3】:

如果您的目标只是更新类型值,那么类似下面的语句可能会起作用:

UPDATE OBS_MASTER
SET TYPE='CONTIN'
WHERE TYPE='ASBESTOS' and 
  PROJECT not in 
  (select distinct PROJECT 
   from OBS_MASTER 
   where TYPE='CONTIN')

希望这会有所帮助。

【讨论】:

我没有尝试更新表本身。感谢您的帮助

以上是关于根据每个唯一标识符的条件更新值的主要内容,如果未能解决你的问题,请参考以下文章

SQL:如何选择每个唯一标识符的值最低的记录

约束条件

通过唯一标识符组合查询结果的行?

如何更新没有任何数据的行以唯一标识该行?

查找唯一标识符重复的每个字段的最大序列号

约束条件