2016-01-20 64 views
3

做列對的比較,試圖發現任何不符合SQL服務器列比較,包括空/非空

SELECT 
    RecID, 
    Field1, 
    Field2 
FROM 
    TestTable 
WHERE 
    Field1 != Field2 

不過,我想在我的支票空值。空兩列是有效的,在一列但空,而不是在其他無效所以需要被包含在輸出

SELECT 
    RecID, 
    Field1, 
    Field2 
FROM 
    TestTable 
WHERE 
    (Field1 != Field2) 
    OR (Field1 IS NULL AND Field2 IS NOT NULL) 
    OR (Field1 IS NOT NULL AND Field2 IS NULL) 

這是寫的最好的方法,還是有一個整潔/更好方式做Null/Not Null比較?

+0

這對我來說很好,這樣做的問題是什麼? – JonH

+0

@JonH這樣做可能沒有任何問題。我知道這種方式奏效,但想知道是否有一個「適當」的方式來做到這一點。如果我這樣做的問題就是這樣,這只是我上面的示例非常簡單 - 我的實際比較查詢比較多(更多的列),所以如果有比較好/更快/更短的方式來進行比較它可能使我的查詢更容易編寫。 – Midavalo

+2

這是正確的方法。 – JonH

回答

2

我還以爲你可以多一點濃縮的方式編寫過濾條件:

SELECT 
    ID, 
    Field1, 
    Field2 
FROM 
    TestTable 
WHERE 
    NOT((Field1 = Field2) OR (Field1 IS NULL AND Field2 IS NULL)) 
; 

但是,這個查詢將產生不正確的結果。 您的變體是正確的。


Connect item關於提議IS DISTINCT FROM操作員通過@Heinzi所提及this answer有一個鏈接到一個很好的職位由保羅·懷特:Undocumented Query Plans: Equality Comparisons

在那篇文章中,Paul解釋說查詢處理器已經有了這個操作符,它用於INTERSECT查詢。

你舉的例子可以改寫爲:

SELECT 
    ID, 
    Field1, 
    Field2 
FROM 
    TestTable AS T 
WHERE 
    NOT EXISTS 
    (
     SELECT T.Field1 

     INTERSECT 

     SELECT T.Field2 
    ) 
; 
  • 它產生正確的結果
  • 它具有良好的執行計劃
  • 在這種形式很容易添加更多的字段進行比較
+0

我和你一樣(反轉連接條目中的條件),但是,正如你所意識到的那樣,它不起作用。原因是[非常規數據](https://en.wikipedia.org/wiki/Law_of_excluded_middle)不適用於SQL的[三元邏輯](https://en.wikipedia.org/wiki/Three-有價值的邏輯#邏輯):WHERE NULL = NULL和WHERE NULL!= NULL都產生NULL,因此沒有記錄。 – Heinzi

+0

使用'WHERE NOT EXISTS(SELECT Field1 INTERSECT SELECT Field2)'給出了與'WHERE(Field1!= Field2)OR(Field1 IS NULL AND Field2 IS NOT NULL)OR(Field1 IS NOT NULL AND Field2 IS NULL)'但是更短,更整齊且易於閱讀。謝謝@Vladimir – Midavalo

1

在未來的SQL Server版本中,希望有 - IS DISTINCT FROM運算符。 Go ahead and vote for it, if you like.

在此之前,您唯一的選擇就是解決它,就像您已經這樣做了。還有其他方法可以編寫它 - 另一個common variant(a <> b OR a IS NULL OR b IS NULL) AND NOT (a IS NULL AND b IS NULL) - 但我認爲解決方案必須具有更高的可讀性。

+1

連接項目和你引用的答案與Paul White的帖子有關的鏈接可以通過使用'INTERSECT'技巧實現'IS DISTINCT FROM'。 –