T-SQL:根据列的UPDATE表

时间:2019-06-25 10:18:45

标签: sql-server tsql sql-update

TLDNR :如何根据列更新表?

问题情况:当前列SortingNumber充满了不良数据。

解决方案:根据SortingNumber将新值重新分配给Parent。对于最低的当前SortingNumber (按SortingNumberParent应当为1,对于随后的每个数据集,该值应递增1。

Current data:                         Desired result:

ID | Parent | SortingNumber   >>      ID | Parent | SortingNumber 
1  |   1    |   3             >>      1  |   1    |   1 
2  |   1    |   4             >>      2  |   1    |   2 
3  |   1    |   5             >>      3  |   1    |   3 
4  |   2    |   8             >>      4  |   2    |   1           
5  |   2    |   10            >>      5  |   2    |   2           
6  |   2    |   13            >>      6  |   2    |   3          

实际问题:我在弄清楚如何更新与其父代相对应的数据集时遇到了麻烦。

我的脚本当前以增量方式更新所有值,并且未按Parent对其进行分组。

我当前的解决方案:

DECLARE @lastSN INTEGER = 0;

WITH toUpdate AS
(
    SELECT 
        T1.*,
        -- "calculate" the sorting number from the row above    
        LAG(T1.SortingNumber + 1, 1, 1) OVER (ORDER BY T1.SortingNumber) AS [newSortNumber]
    FROM 
        T AS T1 
    INNER JOIN 
        T AS T2 ON T1.Parent = T2.ID
)
UPDATE toUpdate
SET
    @lastSN = CASE WHEN [newSortNumber] = 1 AND @lastSN = 0 THEN 1 ELSE @lastSN + 1 END,
    toUpdate.SortingNumber = @lastSN 
;

结果是:

    ID | Parent | SortingNumber   
    1  |   1    |   1             
    2  |   1    |   2             
    3  |   1    |   3             
    4  |   2    |   4             
    5  |   2    |   5            
    6  |   2    |   6

我想我的问题可以表述为:如何根据Parent列更新数据集?

PS :如果您想自己尝试一下,这里是CREATE语句

CREATE TABLE T 
(
    ID INT IDENTITY(1,1) PRIMARY KEY, 
    Parent INT FOREIGN KEY REFERENCES T(ID),
    SortingNumber INT
);   
GO  

INSERT INTO T (Parent, SortingNumber) 
VALUES (1, 3), (1, 4), (1, 5), (2, 8), (2, 10), (2, 13);

2 个答案:

答案 0 :(得分:1)

您可以使用row_number通过Parent分区和SortingNumber排序来实现此目的。

WITH cte AS (
SELECT 
    * ,  
    ROW_NUMBER() OVER (PARTITION BY Parent ORDER BY SortingNumber) AS NewSortingNumber
FROM T

)
UPDATE cte
SET SortingNumber = NewSortingNumber

窗口函数使用父级在表内创建小表,因此我们有两个子集,一个子集用于Parent = 1,另一个子集用于Parent =2。然后它使用ORDER BY来知道应该从哪一行开始计数(从1开始)。第一行是针对Parent = 1和ID = 1的,因此它得到1,下一行得到2,依此类推。请在此处查看更多details

答案 1 :(得分:-1)

作为替代方案,您可以按照患者的身份和ID排序:

UPDATE tt

SET sortingnumber = drank from (select *, DENSE_RANK() OVER (order by Parent, ID) as drank from tt ) a where tt.ID=a.id and tt.parent=a.parent

select * from tt