2011-10-03 24 views
3

我需要連接兩個或多或少相同的表(一個是登臺表數據)。更好的方法來加入空值比選擇一個魔法值?

某些列可以爲空,當值爲空時,我的合併語句中的連接不匹配。 (這是空值的正常行爲。)

問題是,當它們不匹配時會導致行被刪除並重新創建,更改實際表中行的值標識。

我知道我可以做這樣的事情的加入空:

on coalesce(target.SomeId, -9999) = coalesce(source.SomeId, -9999) 

,但我不喜歡挑選出一個數字,我希望永遠不會使用。 (感覺很髒)。

有沒有更好的方法來創建一個可以爲null的列上的連接,而不是像使用這樣的幻數?

回答

-1

特殊字符? 否則,你可以嘗試:

on (target.SomeId is null OR source.SomeId is null OR target.SomeId = source.SomeId) 
0
ON ((target.SomeId IS NULL) AND (source.SomeId IS NULL)) 
OR ((target.SomeId IS NOT NULL) AND (source.SomeId IS NOT NULL) 
AND (target.SomeId = source.SomeId))) 
+1

第二個條件(檢查雙方都不爲空)似乎是多餘的;一個空值不會比較等於一個不是。 –

+0

這就是Linq2Sql在執行'Object.Equals(target.SomeId,source.SomeId)時產生的' – Magnus

+0

不夠公平,但我敢打賭它會被優化掉。 –

5

讓我們去這個:

target.SomeId = source.SomeId 
    or (target.SomeId is null and source.SomeId is null) 

從概念上講,這應該是有意義的。也就是說,兩個值都是null或兩個值彼此相等。這也應該表現更好,因爲合併強制進行表掃描。我已經將coalesce風格轉換爲上述風格,並取得了巨大的性能提升。

0

假設你的意思是不是加入關鍵的一部分列,然後

...and (isnull(source.ColX, target.ColX) = isnull(target.ColX, source.ColX) 
     or (source.ColX is null and target.ColX is null)) 

應包括所有的可能性:第一行捕捉如果這兩個值不爲空或只有一個值不爲空,並且如果兩個都爲空,則捕獲第二行。很醜陋,但是當你的系統中有太多的空值時會發生這種情況。

0

結果很奇怪,包含源自INNER JOIN的行和來自源和目標表(例如{SC,TC},{SC,TD},{SC,TE},{ SD,TC},{SD,TD},{SD,TE})。

請看下面的例子:

DECLARE @Source TABLE (SomeId INT NULL, Name VARCHAR(10) NOT NULL); 
DECLARE @Target TABLE (SomeId INT NULL, Name VARCHAR(10) NOT NULL); 

INSERT @Source VALUES (1,'S-A'),(2,'S-B'),(NULL,'S-C'),(NULL,'S-D'); 
INSERT @Target VALUES (1,'T-A'),(2,'T-B'),(NULL,'T-C'),(NULL,'T-D'),(NULL,'T-E'),(6,'T-F'); 

SELECT s.*, t.* 
FROM @Source s 
INNER JOIN @Target t ON s.SomeId = t.SomeId OR s.SomeId IS NULL AND t.SomeId IS NULL; 

SELECT s.*, t.* 
FROM @Source s 
INNER JOIN @Target t ON ISNULL(s.SomeId,-9999) = ISNULL(t.SomeId,-9999); 

結果:

SomeId  Name  SomeId  Name 
----------- ---------- ----------- ---------- 
1   S-A  1   T-A <- INNER JOIN 
2   S-B  2   T-B <- INNER JOIN 
NULL  S-C  NULL  T-C <- "CROSS JOIN" 
NULL  S-C  NULL  T-D <- "CROSS JOIN" 
NULL  S-C  NULL  T-E <- "CROSS JOIN" 
NULL  S-D  NULL  T-C <- "CROSS JOIN" 
NULL  S-D  NULL  T-D <- "CROSS JOIN" 
NULL  S-D  NULL  T-E <- "CROSS JOIN" 
相關問題