2008-11-17 83 views
30

我相信作出愚蠢的錯誤,但我想不出什麼:SQL查詢的問題:SELECT ... NOT IN

在SQL Server 2005,我想選擇所有的客戶除了那些誰之前,已經做了預約凌晨2點

當我運行此查詢:

SELECT idCustomer FROM reservations 
WHERE idCustomer NOT IN 
    (SELECT distinct idCustomer FROM reservations 
    WHERE DATEPART (hour, insertDate) < 2) 

我得到0的結果。

SELECT idCustomer FROM reservations 

回報152.000結果和 「NOT IN」 部分:

SELECT distinct idCustomer FROM reservations 
WHERE DATEPART (hour, insertDate) < 2 

只返回284行

+0

爲什麼你會放一個鮮明在你不在? (1,1,2,3,4,4,4,4,4)是5嗎?在不在乎是否有重複。 – 2008-11-17 18:18:20

+1

當然,我有點絕望,試圖一切:) – 2008-11-17 20:23:23

回答

53
SELECT distinct idCustomer FROM reservations 
WHERE DATEPART (hour, insertDate) < 2 
    and idCustomer is not null 

確保您的列表參數不包含空值。

這裏有一個解釋:

WHERE field1 NOT IN (1, 2, 3, null) 

是一樣的:

WHERE NOT (field1 = 1 OR field1 = 2 OR field1 = 3 OR field1 = null) 
  • 這最後比較的計算結果爲空。
  • null與布爾表達式的其餘部分進行OR運算,產生null。 (*)
  • null被否定,產生null。
  • null不爲真 - where子句只保留真正的行,因此所有行都被過濾。

(*)編輯:這個解釋很不錯,但我想解決一件事,以避免未來的挑剔。 (TRUE或NULL)將評估爲TRUE。例如,如果field1 = 3,則這是相關的。該TRUE值將被否定爲FALSE,並且該行將被過濾。

+0

就是這樣,謝謝!我仍然不明白爲什麼。非空值不應該被空值過濾,對吧? – 2008-11-17 17:12:39

+0

偉大的解釋大衛,非常感謝! – 2008-11-17 17:14:25

2

由於它是SQL 2005,你也可以嘗試這個 它類似於Oracle的MINUS命令(UNION的對面)

不過我也建議加入DATEPART(小時,insertDate)列調試

SELECT idCustomer FROM reservations 
EXCEPT 
SELECT idCustomer FROM reservations WHERE DATEPART (hour, insertDate) < 2 
0
SELECT Reservations.idCustomer FROM Reservations (nolock) 
LEFT OUTER JOIN @reservations ExcludedReservations (nolock) ON Reservations.idCustomer=ExcludedReservations.idCustomer AND DATEPART(hour, ExcludedReservations.insertDate) < 2 
WHERE ExcludedReservations.idCustomer IS NULL AND Reservations.idCustomer IS NOT NULL 
GROUP BY Reservations.idCustomer 

[更新:增加了額外的標準來處理idCustomer是NULL,這顯然是主要問題樓主有]

+0

嗨凱文,問題是客戶Id是可空的,並@David指出,但很多謝謝! – 2008-11-17 17:30:41

+0

好的。爲了完整性,在附加標準中添加:-P 我沒有數據可以嘗試,但我很想知道執行計劃中的NOT IN與OUTER JOIN的區別。 無論如何,很高興你的問題得到解決。 – 2008-11-17 17:36:53

0

很抱歉,如果我錯過了這個觀點,但是下面不會做你想做的事情嗎?

SELECT distinct idCustomer FROM reservations 
WHERE DATEPART(hour, insertDate) >= 2 
+0

我在想同樣的事情......但是,如果一個客戶有兩個預訂,一個在2Am之前,一個在之後,你會包括他,而他不會。 – 2008-11-17 17:53:40

6

它總是危險有NULLIN列表 - 它常常表現出預期的IN,但不是爲NOT IN

IF 1 NOT IN (1, 2, 3, NULL) PRINT '1 NOT IN (1, 2, 3, NULL)' 
IF 1 NOT IN (2, 3, NULL) PRINT '1 NOT IN (2, 3, NULL)' 
IF 1 NOT IN (2, 3) PRINT '1 NOT IN (2, 3)' -- Prints 
IF 1 IN (1, 2, 3, NULL) PRINT '1 IN (1, 2, 3, NULL)' -- Prints 
IF 1 IN (2, 3, NULL) PRINT '1 IN (2, 3, NULL)' 
IF 1 IN (2, 3) PRINT '1 IN (2, 3)' 
-1
SELECT MIN(A.maxsal) secondhigh 
FROM (
     SELECT TOP 2 MAX(EmployeeBasic) maxsal 
     FROM M_Salary 
     GROUP BY EmployeeBasic 
     ORDER BY EmployeeBasic DESC 
    ) A 
-1
select * from table_name where id=5 and column_name not in ('sandy,'pandy');