【问题标题】:update a column when multiple records of another columns of same table matches当同一表的另一列的多个记录匹配时更新列
【发布时间】:2019-05-28 10:45:07
【问题描述】:

我有如下表格:

            Input table:
            RequestNumber            TrackName         Date
            -----------------------------------------------------------
            02209                    Middle         2017-05-28 00:00:00
            0263                     Middle         2017-06-29 00:00:00
            0633                     Middle         2017-09-10 00:00:00
            0762                     Back           2017-06-23 00:00:00
            0762                     Front          2017-06-23 00:00:00
            0762                     Middle         2017-06-23 00:00:00
            01839                    Middle         2017-03-09 00:00:00

我需要检查“TrackName”的“RequestNumber”和“Date”是否相同。 如果“RequestNumber”和“Date”的多个reacords匹配,那么我应该将“TrackName”列更新为“All three”,如下所示 输出示例(本例中有 3 条记录匹配)

            Output table:
            RequestNumber            TrackName         Date
            -----------------------------------------------------------
            02209                    Middle         2017-05-28 00:00:00
            0263                     Middle         2017-06-29 00:00:00
            0633                     Middle         2017-09-10 00:00:00
            0762                     All three      2017-06-23 00:00:00
            01839                    Middle         2017-03-09 00:00:00

要获得上述设计的输出,这是我尝试过的 SQL。但是,它会将所有 TrackName 更新为全部三个。

            UPDATE a 
            SET a.[TrackName] = 'All three'
            FROM Table1 as a
            INNER JOIN 
            (SELECT [RequestNumber], row_number() OVER (ORDER BY [RequestNumber] DESC) as rowNumber
            FROM Table1 ) drRowNumbers ON drRowNumbers.[RequestNumber] = a.[RequestNumber] and drRowNumbers.[Date] = a.[Date]

希望我已经正确解释了这一点。我在做什么?请问有什么问题可以解决吗?

注意:记录是动态的,所以不能硬编码(如果有的话)。

谢谢。

【问题讨论】:

  • 您希望 0762 的两个记录都保留在那里,TrackName = 'All three'?还是想同时删除第二行?
  • 如果“RequestNumber”和“Date”匹配(如示例所示),则合并所有记录以提供字符串“All three”。因为“TrackName”只有 3 个类别(即 Middle、Back 和 front)。
  • 这表示应该删除另外两行吧?
  • 是的。但是,输出应该如图所示。

标签: sql-server sql-server-2017


【解决方案1】:

试试这个。这将返回“All 3”而不是“All Three”-

SELECT RequestNumber,
CASE 
    WHEN COUNT(*) = 1 THEN MAX(TrackName) 
    ELSE 'All ' + CAST( COUNT(*) AS VARCHAR) 
END TrackName,
Date
FROM your_table
GROUP BY RequestNumber,Date

【讨论】:

    【解决方案2】:

    我想你想要SELECT 声明:

    SELECT t1.RequestNumber, (CASE WHEN COUNT(DISTINCT t1.TrackName) = t2.TrackNo 
                                   THEN CONCAT('All ', t2.TrackNo)  
                                   ELSE MIN(t1.TrackName) 
                              END) AS TrackName, t1.Date
    FROM table1 t1 CROSS JOIN
         (SELECT COUNT(DISTINCT TrackName) AS TrackNo FROM table1) AS t2
    GROUP BY t1.RequestNumber, t1.Date;
    

    【讨论】:

      【解决方案3】:

      这不仅仅是一次更新,也是一次删除。
      这意味着您必须有一个两步过程 - 一个更新相关记录,然后删除第一步创建的重复项。

      当两个步骤在事务中连接时,这可以使用几个使用窗口函数的公共表表达式来完成,例如 count() over()row_number() over()

      首先,创建并填充示例表(在您以后的问题中保存我们这一步):

      DECLARE @T AS TABLE
      (
          RequestNumber int,
          TrackName varchar(10),
          [Date] datetime2
      );
      
      INSERT INTO @T (RequestNumber, TrackName, Date) VALUES
      (02209, 'Middle', '2017-05-28 00:00:00'),
      (0263, 'Middle', '2017-06-29 00:00:00'),
      (0633, 'Middle', '2017-09-10 00:00:00'),
      (0762, 'Back', '2017-06-23 00:00:00'),
      (0762, 'Front', '2017-06-23 00:00:00'),
      (0762, 'Middle', '2017-06-23 00:00:00'),
      (01839, 'Middle', '2017-03-09 00:00:00');
      

      接下来,启动一个try 块和一个事务:

      BEGIN TRY
      BEGIN TRANSACTION;
      

      然后,识别并更新相关记录:

      WITH CTE AS
      (
          SELECT  RequestNumber, 
                  TrackName, 
                  Date,
                  COUNT(TrackName) OVER(PARTITION BY RequestNumber, Date) As Cnt
          FROM @T
      )
      
      UPDATE CTE
      SET TrackName = 'All Three'
      WHERE Cnt = 3;
      

      接下来,删除重复项:

      WITH CTE AS
      (
          SELECT  RequestNumber, 
                  TrackName, 
                  Date,
                  ROW_NUMBER() OVER(PARTITION BY RequestNumber, Date ORDER BY TrackName) As Rn
          FROM @T
      )
      
      DELETE 
      FROM CTE 
      WHERE Rn > 1;
      

      提交事务并关闭try 块:

      COMMIT TRANSACTION;
      END TRY
      

      使用 catch 块回滚事务:

      BEGIN CATCH
          IF @@TRANCOUNT > 0
              ROLLBACK TRANSACTION
      
          -- you might want to print the result of ERROR_MESSAGE() here...
      END CATCH
      

      最后,选择查看更改:

      SELECT  RequestNumber, 
              TrackName, 
              Date
      FROM @T
      

      结果:

      RequestNumber   TrackName   Date
      2209            Middle      28.05.2017 00:00:00
      263             Middle      29.06.2017 00:00:00
      633             Middle      10.09.2017 00:00:00
      762             All Three   23.06.2017 00:00:00
      1839            Middle      09.03.2017 00:00:00
      

      You can see a live demo on rextester(减去那里不允许的事务部分和无论如何没有事务不相关的 try...catch)

      【讨论】:

        【解决方案4】:

        试试这个

        第 1 步将其中一个记录设置为全部三个

        update table1
        set TrackName = 'All Three'
        where requestnumber in (select requestnumber
        from table1
        group by requestnumber,[date]
        having count(*) = 3)
        and trackname = 'Front'
        

        第 2 步删除不再需要的数据

        delete table1
        where requestnumber in (select requestnumber
        from table1
        group by requestnumber,[date]
        having count(*) = 3)
        and trackname <> 'All Three'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-18
          • 1970-01-01
          • 2020-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多