Sql-Server
使用視窗函式繼承非空值?
在 SQL Server 中,我經常看到這被稱為“塗抹”,並且有關於使用“古怪更新”來做到這一點的部落格文章。但是我將如何使用視窗函式來做到這一點。例如,如果我有:
name date happiness ---- ---- --------- John 1/3 20 John 1/4 NULL John 1/5 NULL John 1/6 NULL John 1/7 18 Mary 1/2 35 Mary 1/3 NULL Mary 1/4 -15 Mary 1/6 NULL Mary 1/7 0
有沒有辦法做類似的事情:
SELECT [name], [date], CARRY([happiness]) OVER (PARTITION BY [name] ORDER BY [date])
這樣中間結果看起來像:
name date happiness ---- ---- --------- John 1/3 20 John 1/4 20 John 1/5 20 John 1/6 20 John 1/7 18 Mary 1/2 35 Mary 1/3 35 Mary 1/4 -15 Mary 1/6 -15 Mary 1/7 0
CARRY
顯然不是一個真正的功能,只是想要那個功能。
您也可以使用
APPLY()
運算符來獲取"last"
not null
happiness
SELECT * FROM [Data] d CROSS APPLY ( SELECT TOP 1 happiness FROM [Data] x WHERE x.[name] = d.[name] AND x.[date] <= d.[date] AND x.happiness IS NOT NULL ORDER BY x.[date] DESC ) h
您可以使用遞歸 CTE 和 COALESCE 來返回最新的非 NULL 值。請參閱此小提琴以獲取工作範例。
在範例中,我首先使用 CTE 創建一個偽 ID 列以用於遞歸 CTE。然後在遞歸 CTE 中,我們選擇 ID = 1 行(最早的行)作為錨點,並為每個名稱組遞歸地按 ID 選擇下一行。如果目前值為 NULL 表示幸福,則 COALESCE 函式將選擇先前的值。
詢問:
;WITH DataC AS( SELECT ROW_NUMBER() OVER (PARTITION BY name ORDER BY date) AS ID, [name], [date], [happiness] FROM Data ), CTE AS ( SELECT ID, [name], [date], [happiness] FROM DataC WHERE ID = 1 UNION ALL SELECT d.ID, d.[name], d.[date], COALESCE(d.[happiness], c.happiness) AS happiness FROM DataC d INNER JOIN CTE c ON c.Name = d.Name AND c.ID = d.ID - 1 ) SELECT * FROM CTE ORDER BY name, date
結果:
ID name date happiness ------------------------------------------------- 1 John 2020-01-03 00:00:00.000 20 2 John 2020-01-04 00:00:00.000 20 3 John 2020-01-05 00:00:00.000 20 4 John 2020-01-06 00:00:00.000 20 5 John 2020-01-07 00:00:00.000 18 1 Mary 2020-01-01 00:00:00.000 35 2 Mary 2020-01-02 00:00:00.000 35 3 Mary 2020-01-03 00:00:00.000 -15 4 Mary 2020-01-04 00:00:00.000 -15 5 Mary 2020-01-05 00:00:00.000 0