2011-04-21 233 views
25

我需要構建一個查詢,根據make-model-serial number組合,向我顯示錶1中的記錄,但不在表2中的記錄。SQL Server - NOT IN

我知道事實上有4條記錄不同,但我的查詢總是空白。

SELECT * 
FROM Table1 WHERE MAKE+MODEL+[Serial Number] NOT IN 
(SELECT make+model+[serial number] FROM Table2) 

表1有5條記錄。

當我將查詢更改爲IN時,我得到1條記錄。我在做什麼錯了NOT

+3

你的表中是否有空值? – tobias86 2011-04-21 19:10:06

+0

也許發佈您的數據將有所幫助。語法看起來不錯。 (雖然psuedo-key有點不好意思) – Randy 2011-04-21 19:11:29

回答

35

這是因爲the way NOT IN works

爲了避免這些麻煩(和在許多情況下更快的查詢),我總是喜歡NOT EXISTS:

SELECT * 
FROM Table1 t1 
WHERE NOT EXISTS (
    SELECT * 
    FROM Table2 t2 
    WHERE t1.MAKE = t2.MAKE 
    AND t1.MODEL = t2.MODEL 
    AND t1.[Serial Number] = t2.[serial number]); 
+0

多數民衆贊成它!謝謝! – 2011-04-21 19:14:32

+0

查看我的編輯(在閱讀Joe的良好答案後,我改進了我的答案) – 2011-04-21 19:17:19

0

使用LEFT JOIN檢查右側的空值。

SELECT a.Id 
FROM TableA a 
LEFT JOIN TableB on a.Id = b.Id 
WHERE b.Id IS NULL 

上面將匹配基於每個Id列表A表B和,然後給你其中B側是空的行。

+0

這通常起作用,但IMO並不是一個很好的通用解決方案,因爲如果TableB中存在連接謂詞的多行,並且如果b .Id恰好是一個空列,你可以得到一個誤報。在很多情況下,這是一個有效的解決方案,但是(取決於數據) – 2011-04-21 19:15:10

+0

@DaveMarkle,是的,非常好的警告,謝謝。 – 2011-04-21 19:16:07

6

你可能比單獨比較字段更好,而不是連接字符串。

SELECT t1.* 
    FROM Table1 t1 
     LEFT JOIN Table2 t2 
      ON t1.MAKE = t2.MAKE 
       AND t1.MODEL = t2.MODEL 
       AND t1.[serial number] = t2.[serial number] 
    WHERE t2.MAKE IS NULL 
+0

更好 - 在更快? :) – 2011-04-21 19:13:38

+0

我喜歡這個想法 – tobias86 2011-04-21 19:13:53

+0

@xrum:對於列上的索引,我當然會這麼認爲。 – 2011-04-21 19:15:19

0

一個問題可能是,如果任一品牌,型號,或[序號]爲空,值永遠不會返回。因爲帶空值的字符串連接總是會導致null,而不是()中的null將始終不返回任何內容。造成這種情況的補救方法是使用運營商如ISNULL(做,「」)+ ISNULL(型號,「」)等

1
SELECT [T1].* 
FROM [Table1] AS [T1] 
WHERE NOT EXISTS (SELECT 
    1 AS [C1] 
    FROM [Table2] AS [T2] 
    WHERE ([T2].[MAKE] = [T1].[MAKE]) AND 
     ([T2].[MODEL] = [T1].[MODEL]) AND 
     ([T2].[Serial Number] = [T1].[Serial Number]) 
); 
1
SELECT * FROM Table1 
WHERE MAKE+MODEL+[Serial Number] not in 
    (select make+model+[serial number] from Table2 
    WHERE make+model+[serial number] IS NOT NULL) 

爲我工作,其中make+model+[serial number]是一個字段名稱