SQL Server:根据条件交换两行

时间:2018-04-19 14:47:20

标签: sql sql-server

假设在SQL Server中使用此数据命名 Sales 的表

--------------------------------------------
Id      |  Customer_Id      |  Rate  |  Pid
--------------------------------------------
180     |  374              |  1     |  A01
277     |  374              |  0     |  NULL
346     |  785              |  1     |  D03
476     |  785              |  0     |  NULL
1821    |  1234             |  0     |  E07
25951   |  1951             |  1     |  K73

如何更新我的表格以在具有相同customer_Id的行之间交换评分 Pid 值,因此我可以得到如下结果:

--------------------------------------------
Id      |  Customer_Id      |  Rate  |  Pid
--------------------------------------------
180     |  374              |  0     |  NULL
277     |  374              |  1     |  A01
346     |  785              |  0     |  NULL
476     |  785              |  1     |  D03
1821    |  1234             |  0     |  E07
25951   |  1951             |  1     |  K73

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

如果总是每个客户最多只有两个记录,那么您可以使用以下查询:

SELECT ID,  Customer_Id, 
       CASE 
          -- 2 records per Customer_id -> swap
          WHEN COUNT(*) OVER (PARTITION BY Customer_id) = 2 THEN
            CASE       
               WHEN ROW_NUMBER() OVER (PARTITION BY Customer_id ORDER BY ID) = 1 
                  THEN LEAD(Rate) OVER (PARTITION BY Customer_id ORDER BY ID)
               ELSE LAG(Rate) OVER (PARTITION BY Customer_id ORDER BY ID)
            END
          -- 1 record per Customer_id -> don't swap
          ELSE Rate
       END,
       CASE 
          WHEN COUNT(*) OVER (PARTITION BY Customer_id) = 2 THEN
            CASE       
               WHEN ROW_NUMBER() OVER (PARTITION BY Customer_id ORDER BY ID) = 1 
                  THEN LEAD(Pid) OVER (PARTITION BY Customer_id ORDER BY ID)
               ELSE LAG(Pid) OVER (PARTITION BY Customer_id ORDER BY ID)
            END
          ELSE Pid
       END
FROM Sales

Demo here

修改

如果您想要UPDATE,那么您可以将上述查询包含在CTE中并对CTE进行更新:

;WITH ToUpdate AS (
SELECT ID,  Customer_Id, Rate, Pid, 
       COUNT(*) OVER (PARTITION BY Customer_id) AS cnt,
       CASE       
         WHEN ROW_NUMBER() OVER (PARTITION BY Customer_id ORDER BY ID) = 1 
           THEN LEAD(Rate) OVER (PARTITION BY Customer_id ORDER BY ID)
         ELSE LAG(Rate) OVER (PARTITION BY Customer_id ORDER BY ID)
       END AS NewRate,
       CASE       
         WHEN ROW_NUMBER() OVER (PARTITION BY Customer_id ORDER BY ID) = 1 
           THEN LEAD(Pid) OVER (PARTITION BY Customer_id ORDER BY ID)
         ELSE LAG(Pid) OVER (PARTITION BY Customer_id ORDER BY ID)
       END AS NewPid
FROM Sales)
UPDATE ToUpdate
SET Rate = NewRate, Pid = NewPid
WHERE cnt = 2

Demo here

答案 1 :(得分:0)

这样做会有一点需要注意,你最多只有两条具有相同Customer_Id的记录......

update Sales 
set Rate = 
    (
        select Rate from Sales sls 
        where sls.Customer_Id = Sales.Customer_Id 
             and sls.Rate <> Sales.Rate
    )