此問題是我的舊問題here的變體。我希望用一個例子來解釋這個問題。所以使用CTE更新上一行值的值
樣本數據
這裏是樣本數據一起工作:
DECLARE @Test TABLE (GID int, Seq int,
IsLive bit, Eff date,
Name varchar(50), Salary decimal)
INSERT INTO @Test VALUES (1, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (1, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (1, 3, 1, '01-10-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (1, 4, 0, '01-11-2012', NULL, NULL)
INSERT INTO @Test VALUES (1, 5, 1, '01-12-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (2, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (2, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 3, 1, '01-10-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (2, 4, 0, '01-11-2012', 'GSM', NULL)
INSERT INTO @Test VALUES (2, 5, 1, '01-12-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (3, 1, 1, '01-01-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (3, 2, 0, '01-02-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 2, 0, '01-02-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (4, 3, 0, '01-03-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 1, 0, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 2, 1, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (5, 3, 0, '01-03-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 2, 0, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (6, 3, 1, '01-03-2012', NULL, NULL)
SELECT * FROM @Test
下面,有兩個樣品結果集。雖然片段展示了插入的一點是要顯示什麼可接受輸出設定將如下所示:
樣本輸出#1
在數據設置如下時,行具有IsLive=0
然後從值其列必須在其下方的IsLive=1
跳過NULL值的行上寫入相同列的值。在第一行IsLive=0
行之前忽略任何IsLive=1
行。
INSERT INTO @Test VALUES (1, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (1, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (1, 3, 1, '01-10-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (1, 4, 0, '01-11-2012', NULL, NULL)
INSERT INTO @Test VALUES (1, 5, 1, '01-12-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (2, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 3, 1, '01-10-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 4, 0, '01-11-2012', 'GSM', NULL)
INSERT INTO @Test VALUES (2, 5, 1, '01-12-2012', 'GSM', NULL)
INSERT INTO @Test VALUES (3, 1, 1, '01-01-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (3, 2, 0, '01-02-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 2, 0, '01-02-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (4, 3, 0, '01-03-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 1, 0, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 2, 1, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (5, 3, 0, '01-03-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 2, 0, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (6, 3, 1, '01-03-2012', 'LSI', NULL)
SELECT * FROM @Test AS FakedOutput_1
樣品輸出#2
在數據設置如下時,行具有IsLive=0
然後從它的列的值必須在寫的相同列的值上的行,其中IsLive=1
在其下方。具有NULL值的列採用前一行中的值。
INSERT INTO @Test VALUES (1, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (1, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (1, 3, 1, '01-10-2012', 'RTA', NULL)
-- <- the following row is different from prev
INSERT INTO @Test VALUES (1, 4, 0, '01-11-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (1, 5, 1, '01-12-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 1, 1, '01-08-2012', 'RTS', NULL)
INSERT INTO @Test VALUES (2, 2, 0, '01-09-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 3, 1, '01-10-2012', 'RTA', NULL)
INSERT INTO @Test VALUES (2, 4, 0, '01-11-2012', 'GSM', NULL)
INSERT INTO @Test VALUES (2, 5, 1, '01-12-2012', 'GSM', NULL)
INSERT INTO @Test VALUES (3, 1, 1, '01-01-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (3, 2, 0, '01-02-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (4, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (4, 2, 0, '01-02-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (4, 3, 0, '01-03-2012', 'FSA', NULL)
INSERT INTO @Test VALUES (5, 1, 0, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (5, 2, 1, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (5, 3, 0, '01-03-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (6, 1, 1, '01-01-2012', NULL, NULL)
INSERT INTO @Test VALUES (6, 2, 0, '01-02-2012', 'LSI', NULL)
INSERT INTO @Test VALUES (6, 3, 1, '01-03-2012', 'LSI', NULL)
SELECT * FROM @Test AS FakedOutput_2
嘗試性解決方案
以下是我想出了這麼遠,但它沒有我的第一個測試案例(GID=1
)
;WITH CTE AS (
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SELECT T.GID, T.SEQ, T.IsLive, NULL cGuid, NULL cSEQ,
cast(0 as bit) cIsLive, T.Name, T.Salary
FROM @Test T
JOIN @Test S ON T.GID = S.GID AND T.Seq = S.Seq AND S.IsLive = 0
-- - - - - - -
UNION ALL
-- - - - - - -
SELECT t.GID, t.SEQ, T.IsLive, c.GID cGID, c.Seq cSEQ,
c.IsLive cIsLive, ISNULL(C.Name, T.Name),
ISNULL(t.Salary, c.Salary)
FROM CTE c
JOIN @Test t ON t.GID = c.GID AND
t.Seq > c.Seq AND
t.IsLive = 1 AND
c.IsLive = 0
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
)
--SELECT * FROM CTE ORDER BY CTE.GID, CTE.Seq
UPDATE t
SET Name = c.Name, Salary = c.Salary
FROM @Test t
JOIN CTE c ON c.GID = t.GID AND c.Seq = t.SEQ
WHERE C.cIsLive IS NOT NULL
@Mahmoud:謝謝,剛剛在修復格式化過程。 – KShan
@GilM自從你釘上前一個以後,你可能會想刺穿它! – KShan
我更新了一篇文章,我似乎無法格式化(或者說我不知道如何格式化)新添加的測試用例:( – KShan