更新数据集中的连续行

时间:2016-07-25 13:08:01

标签: sql sql-server sql-server-2008-r2

我正在尝试将第一行中的EffectiveEndDTM从第二行中的NULL更新为LoadDTM值,同样地将除了最后一行之外的所有行更新为保持为NULL。

EffectiveStartDTM       EffectiveEndDTM CurrentRecInd   LoadID  LoadDTM
2016-06-13 13:05:09.000 NULL            1               130272  2016-06-13 13:05:09.000
2016-06-27 10:27:13.000 NULL            1               133819  2016-06-27 10:27:13.000
2016-07-04 10:05:23.000 NULL            1               135323  2016-07-04 10:05:23.000
2016-07-11 12:11:52.000 NULL            1               136943  2016-07-11 12:11:52.000

最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

由于它是2008 r2,您无法使用2012年推出的lead / lag函数,但这并不意味着您无法获得下一行/上一行的值。你只需要一个子查询:

创建并填充样本表(在将来的问题中保存此步骤)

DECLARE @T As Table
(
    EffectiveStartDTM datetime,
    EffectiveEndDTM datetime,
    CurrentRecInd tinyint,
    LoadID int,
    LoadDTM datetime
)

INSERT INTO @T VALUES
('2016-06-13 13:05:09.000', NULL, 1, 130272, '2016-06-13 13:05:09.000'),
('2016-06-27 10:27:13.000', NULL, 1, 133819, '2016-06-27 10:27:13.000'),
('2016-07-04 10:05:23.000', NULL, 1, 135323, '2016-07-04 10:05:23.000'),
('2016-07-11 12:11:52.000', NULL, 1, 136943, '2016-07-11 12:11:52.000')

更新

UPDATE T1
SET EffectiveEndDTM = (
    SELECT TOP 1 EffectiveStartDTM
    FROM @T T2
    WHERE T2.EffectiveStartDTM > T1.EffectiveStartDTM
    ORDER BY T2.EffectiveStartDTM
)
FROM @T T1

测试更新是否成功:

SELECT EffectiveStartDTM, EffectiveEndDTM, CurrentRecInd, LoadID, LoadDTM
FROM @T 

结果:

EffectiveStartDTM       EffectiveEndDTM         CurrentRecInd LoadID      LoadDTM
----------------------- ----------------------- ------------- ----------- -----------------------
2016-06-13 13:05:09.000 2016-06-27 10:27:13.000 1             130272      2016-06-13 13:05:09.000
2016-06-27 10:27:13.000 2016-07-04 10:05:23.000 1             133819      2016-06-27 10:27:13.000
2016-07-04 10:05:23.000 2016-07-11 12:11:52.000 1             135323      2016-07-04 10:05:23.000
2016-07-11 12:11:52.000 NULL                    1             136943      2016-07-11 12:11:52.000

答案 1 :(得分:1)

DECLARE @T As Table
(
    EffectiveStartDTM datetime,
    EffectiveEndDTM datetime,
    CurrentRecInd tinyint,
    LoadID int,
    LoadDTM datetime
)

INSERT INTO @T VALUES
('2016-06-13 13:05:09.000', NULL, 1, 130272, '2016-06-13 13:05:09.000'),
('2016-06-27 10:27:13.000', NULL, 1, 133819, '2016-06-27 10:27:13.000'),
('2016-07-04 10:05:23.000', NULL, 1, 135323, '2016-07-04 10:05:23.000'),
('2016-07-11 12:11:52.000', NULL, 1, 136943, '2016-07-11 12:11:52.000')

;WITH cte
AS 
(
    SELECT
        *,
        ROW_NUMBER() OVER (ORDER BY LoadID) AS RowId
    FROM
        @T
)

SELECT
    A.LoadID,
    B.LoadDTM
FROM
    cte A LEFT JOIN 
    (
        SELECT cte.RowId -1 AS RowId, cte.LoadDTM  FROM  cte
    ) B ON A.RowId = B.RowId
WHERE
    A.EffectiveEndDTM IS NULL

输出

LoadID  LoadDTM
130272  2016-06-27 10:27:13.000
133819  2016-07-04 10:05:23.000
135323  2016-07-11 12:11:52.000
136943  NULL

更新真实表格

UPDATE YourTable
SET EffectiveEndDTM = R.LoadDTM
FROM
(
    SELECT
       A.LoadID,
       B.LoadDTM
    FROM
        cte A LEFT JOIN 
        (
            SELECT cte.RowId -1 AS RowId, cte.LoadDTM  FROM  cte
        ) B ON A.RowId = B.RowId
    WHERE
        A.EffectiveEndDTM IS NULL
) R
WHERE
    YourTable.LoadID = R.LoadID