SQL查询问题:SELECT ... NOT IN

时间:2008-11-17 16:54:09

标签: sql sql-server

我确实犯了一个愚蠢的错误,但我无法弄清楚:

在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行

7 个答案:

答案 0 :(得分:63)

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

确保list参数不包含空值。

以下是解释:

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

与:

相同
WHERE NOT (field1 = 1 OR field1 = 2 OR field1 = 3 OR field1 = null)
  • 最后一次比较评估为null。
  • 该null与布尔表达式的其余部分进行OR运算,产生null。 (*)
  • null被否定,产生null。
  • null不为true - where子句仅保留true行,因此所有行都被过滤。

(*)编辑:这个解释非常好,但我想解决一件事,以避免未来的挑选。 (TRUE或NULL)将评估为TRUE。例如,如果field1 = 3,则这是相关的。该TRUE值将被否定为FALSE并且该行将被过滤。

答案 1 :(得分:6)

NULL列表中添加IN总是很危险的 - 它通常与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)'

答案 2 :(得分:2)

鉴于它是SQL 2005,你也可以试试这个 它类似于Oracle的MINUS命令(与UNION相反)

但我还建议为调试添加DATEPART(hour,insertDate)列

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

答案 3 :(得分: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,这显然是原始海报的主要问题]

答案 4 :(得分:0)

很抱歉,如果我错过了这一点,但是下面会不会按照自己的意愿行事吗?

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

答案 5 :(得分:-1)

SELECT MIN(A.maxsal) secondhigh
FROM (
      SELECT TOP 2 MAX(EmployeeBasic) maxsal
      FROM M_Salary
      GROUP BY EmployeeBasic
      ORDER BY EmployeeBasic DESC
     ) A

答案 6 :(得分:-1)

select * from table_name where id=5 and column_name not in ('sandy,'pandy');