【问题标题】:Update a table based on the count of specific records in the same table根据同一表中特定记录的计数更新表
【发布时间】:2021-01-27 13:01:48
【问题描述】:

我正在使用 Microsoft SQL Server,并且我的数据库中有一个如下所示的表:

Id   groupName    flag    type 
--------------------------------
1    aaa          0        0   
2    aaa          1        0 
3    aaa          0        0 
4    bbb          0        0   
5    bbb          0        0 
6    bbb          0        0 

我想根据同一张表中特定记录的计数来更新type 列的值。

假设记录按其groupName分组,如果一个组至少有1条flag = 1的记录,则同一组中所有记录的type值应为1,否则为0。

就我而言,我希望得到以下输出。

Id   groupName    flag    type 
--------------------------------
1    aaa          0        1   
2    aaa          1        1 
3    aaa          0        1 
4    bbb          0        0   
5    bbb          0        0 
6    bbb          0        0 

如何使用 SQL 语句做到这一点?

编辑

当然,以下是行不通的。

UPDATE t1 
SET type = CASE
              WHEN ((SELECT COUNT(*) FROM tg) > 0) 
                 THEN 1 
                 ELSE 0 
           END 
FROM [sampleDB].[dbo].[groups] t1 
JOIN (SELECT t2.groupName, t2.flag 
      FROM [sampleDB].[dbo].[groups] t2) tg ON tg.groupName = t1.groupName 
                                            AND tg.flag = 1;

【问题讨论】:

  • @Dale K 以下不起作用。 UPDATE t1 SET type = CASE WHEN ((SELECT COUNT(*) FROM tg) > 0) THEN 1 ELSE 0 END FROM [sampleDB].[dbo].[groups] t1 JOIN (SELECT t2.groupName, t2.flag FROM [ sampleDB].[dbo].[groups] t2) tg ON tg.groupName = t1.groupName AND tg.flag = 1;

标签: sql sql-server tsql


【解决方案1】:

你可以试试下面的-

UPDATE t
SET
    type = case when cnt>=1 then 1 else 0 end
FROM 
    tablename t
    INNER JOIN (select group_name, count(case when flag=1 then 1 end) as cnt from tablename 
                group by group_name)t1
        ON t.group_name= t1.group_name

【讨论】:

  • 感谢您的快速回复。这对我来说非常有用!!我被卡住了,因为我不明白如何使用count(case when flag=1 then 1 end)。你教会了我正确的用法。
【解决方案2】:

我会使用窗口函数:

with toupdate as (
      select g.*, max(flag) over (partition by groupname) as new_flag
      from [sampleDB].[dbo].[groups] g
     )
update toupdate
    set flag = new_flag
    where flag <> new_flag;

注意where 子句,因此只有标志发生变化的行才会更新。即使没有值更改,SQL Server 也会尝试更新行,从而产生开销。 where 子句节省了大部分开销。

【讨论】:

    【解决方案3】:

    您可以使用简单的 JOIN 来简单地做到这一点:

    UPDATE D
    SET Type = 1
    FROM Data D JOIN
    (
      SELECT GroupName
      FROM Data
      WHERE Flag = 1
    ) T ON D.GroupName = T.GroupName;
    

    这是db-fiddle

    【讨论】:

      【解决方案4】:

      这是使用exists语句解决此问题的最有效方法:

      update t1
      set type = 1
      from table t1
      where exists ( select 1 
                     from table t2 
                     where t1.groupname = t2.groupname 
                     and flag = 1
                    )
      

      【讨论】:

      • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。
      【解决方案5】:

      这可能是其他选项

          ;with data
          As (
              Select count(groupname) groupname
                     ,max(flag) flag
                     ,type
      
               From Tablename
             Group by type
             Having count(groupname)>1
                 And max(flag)=1
      )
      Update c
      Set type =1
      From data c
      

      【讨论】:

        猜你喜欢
        • 2023-04-08
        • 1970-01-01
        • 2021-08-02
        • 1970-01-01
        • 1970-01-01
        • 2012-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多