用其他值更新空值
我是 SQL Server 世界的新手。在下面的範例中,我有兩家公司:
- 建築模組
- 紅水泥
每個公司只有一個條目具有列的值
power1, power2, power3
。我需要更新表格,以便每個公司的所有列都有一個值。換句話說,我需要更新所有空白(null)值。
虛構數據範例:
Create Table #Rentarious ( c1 varchar(200) ,yryryryr datetime ,power1 varchar(200) ,power2 varchar(200) ,power3 varchar(200) ) Insert Into #Rentarious VALUES ('Building Blocks','2016','Red','Blue','Green') ,('Red Cement', '2012', 'Pink','Purple','Orange') Insert Into #Rentarious(c1, yryryryr) VALUES ('Building Blocks', '2012') ,('Building Blocks', '2013') ,('Building Blocks', '2014') ,('Red Cement', '2016') ,('Red Cement', '2011')
題
編寫更新語句以將列的空值更新為表
power1, power2, power3
中已列出的值的語法是什麼?
您可以
SET
使用逗號分隔多個欄位。在這種情況下,您只需要根據一些獨特的模式指定記錄c1 and yryryryr
。UPDATE #Rentarious SET power1 = 'Red' , power2 = 'Blue' , power3 = 'Green' WHERE c1 = 'Build Blocks' AND yryryryr = '2012';
編寫更新語句以
power1, power2, power3
使用表中已列出的值更新欄位的空值的語法是什麼?我認為這意味著每家公司的空值都應該根據從一個填充條目中獲取的值來填充,正如您在文章中其他地方所說的那樣,每家公司都有。因此,在虛擬碼中,您的 UPDATE 語句需要如下所示:
UPDATE #Rentarious SET power1 = power1 from the same company’s populated row, power2 = power2 from the same company’s populated row, power3 = power3 from the same company’s populated row WHERE power1 IS NULL AND power2 IS NULL AND power3 IS NULL ;
實現上述模式的一種方法是使用相關子查詢:
UPDATE #Rentarious SET power1 = (SELECT power1 FROM #Rentarious AS src WHERE src.c1 = #Rentarious.c1 AND src.power1 IS NOT NULL), power2 = (SELECT power2 FROM #Rentarious AS src WHERE src.c1 = #Rentarious.c1 AND src.power2 IS NOT NULL), power3 = (SELECT power3 FROM #Rentarious AS src WHERE src.c1 = #Rentarious.c1 AND src.power3 IS NOT NULL) WHERE power1 IS NULL AND power2 IS NULL AND power3 IS NULL ;
雖然這樣會起作用,但這樣的更新可能不是很有效,因為同一個表會被多接觸 3 次才能獲得源值。由於您知道非空值儲存在每家公司的一行中,因此您可以通過使用派生表和專有的“使用連接更新”語法在表上的一次額外傳遞中獲取它們:
UPDATE #Rentarious SET power1 = sub.power1, power2 = sub.power2, power3 = sub.power3 FROM ( SELECT c1, power1, power2, power3 FROM #Rentarious WHERE power1 IS NOT NULL AND power2 IS NOT NULL AND power3 IS NOT NULL ) AS sub WHERE #Rentarious.c1 = sub.c1 AND #Rentarious.power1 IS NULL AND #Rentarious.power2 IS NULL AND #Rentarious.power3 IS NULL ;
您還可以重寫它以使用顯式 JOIN 語法:
UPDATE tgt SET power1 = src.power1, power2 = src.power2, power3 = src.power3 FROM #Rentarious AS tgt INNER JOIN ( SELECT c1, power1, power2, power3 FROM #Rentarious WHERE power1 IS NOT NULL AND power2 IS NOT NULL AND power3 IS NOT NULL ) AS sub ON tgt.c1 = sub.c1 WHERE tgt.power1 IS NULL AND tgt.power2 IS NULL AND tgt.power3 IS NULL ;
如您所見,兩種變體中只有一個子查詢,它提供所有三個值來填充其他行。
但請注意,也可以在不進行任何額外掃描的情況下解決此問題。首先,如果這是一個 SELECT 語句,您可以使用視窗聚合函式在每一行中返回填充行的值,如下所示:
SELECT c1, yryryryr, power1, power2, power3, populatedPower1 = MAX(power1) OVER (PARTITION BY c1), populatedPower2 = MAX(power2) OVER (PARTITION BY c1), populatedPower3 = MAX(power3) OVER (PARTITION BY c1) FROM #Rentarious ;
MAX函式在這種情況下工作,因為它只返回指定集合中非空值的最大值。在您的情況下,在這三種情況下,每個分區只有一個非空值
c1
,因此該函式將返回該值。這將是您問題中範例的查詢結果:c1 yryryryr power1 power2 power3 populatedPower1 populatedPower2 populatedPower3 --------------- ---------- ------ ------ ------ --------------- --------------- --------------- Building Blocks 2012-01-01 NULL NULL NULL Red Blue Green Building Blocks 2013-01-01 NULL NULL NULL Red Blue Green Building Blocks 2014-01-01 NULL NULL NULL Red Blue Green Building Blocks 2016-01-01 Red Blue Green Red Blue Green Red Cement 2012-01-01 Pink Purple Orange Pink Purple Orange Red Cement 2016-01-01 NULL NULL NULL Pink Purple Orange Red Cement 2011-01-01 NULL NULL NULL Pink Purple Orange
所以唯一剩下的就是
SET power1 = populatedPower1, power2 = populatedPower2, power3 = populatedPower3
在 SQL Server 中確實可以這樣做,因為上述 SELECT 查詢的結果可以用作您的 UPDATE 語句的目標。您可以將其用作派生表:
UPDATE tgt SET power1 = populatedPower1, power2 = populatedPower2, power3 = populatedPower3 FROM ( SELECT c1, yryryryr, power1, power2, power3, populatedPower1 = MAX(power1) OVER (PARTITION BY c1), populatedPower2 = MAX(power2) OVER (PARTITION BY c1), populatedPower3 = MAX(power3) OVER (PARTITION BY c1) FROM #Rentarious ) AS tgt WHERE power1 IS NULL AND power2 IS NULL AND power3 IS NULL ;
或將其實現為 CTE(公用表表達式)並使用 CTE 的別名作為目標:
WITH tgt AS ( SELECT c1, yryryryr, power1, power2, power3, populatedPower1 = MAX(power1) OVER (PARTITION BY c1), populatedPower2 = MAX(power2) OVER (PARTITION BY c1), populatedPower3 = MAX(power3) OVER (PARTITION BY c1) FROM #Rentarious ) UPDATE tgt SET power1 = populatedPower1, power2 = populatedPower2, power3 = populatedPower3 WHERE power1 IS NULL AND power2 IS NULL AND power3 IS NULL ;
兩者都可以很好地工作,並導致所有空值都替換為相應的值,即:
c1 yryryryr power1 power2 power3 --------------- ---------- ------ ------ ------ Building Blocks 2016-01-01 Red Blue Green Red Cement 2012-01-01 Pink Purple Orange Building Blocks 2012-01-01 NULL NULL NULL Building Blocks 2013-01-01 NULL NULL NULL Building Blocks 2014-01-01 NULL NULL NULL Red Cement 2016-01-01 NULL NULL NULL Red Cement 2011-01-01 NULL NULL NULL
對此:
c1 yryryryr power1 power2 power3 --------------- ---------- ------ ------ ------ Building Blocks 2016-01-01 Red Blue Green Red Cement 2012-01-01 Pink Purple Orange Building Blocks 2012-01-01 Red Blue Green Building Blocks 2013-01-01 Red Blue Green Building Blocks 2014-01-01 Red Blue Green Red Cement 2016-01-01 Pink Purple Orange Red Cement 2011-01-01 Pink Purple Orange