私はきっと愚かな間違いを犯しているのでしょうが、何が何だかわかりません。
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行しか返らない
SELECT distinct idCustomer FROM reservations
WHERE DATEPART ( hour, insertDate) < 2
and idCustomer is not null
リストパラメーターにNULL値が含まれていないことを確認してください。
以下、解説します。
WHERE field1 NOT IN (1, 2, 3, null)
は同じです。
WHERE NOT (field1 = 1 OR field1 = 2 OR field1 = 3 OR field1 = null)
(*) 編集:この説明はかなり良いのですが、今後の細かい指摘を避けるために、1つだけ対処したいと思います。 (TRUE OR NULL)はTRUEと評価されます。 これは、例えばfield1 = 3の場合に関連します。 このTRUEはFALSEに否定され、その行はフィルタリングされます。
IN
リストに NULL
を含めることは常に危険です。多くの場合、 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)'
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であることを処理するための追加基準を追加しました(元の投稿者が抱えていた主な問題だったようです)。
SELECT MIN(A.maxsal) secondhigh
FROM (
SELECT TOP 2 MAX(EmployeeBasic) maxsal
FROM M_Salary
GROUP BY EmployeeBasic
ORDER BY EmployeeBasic DESC
) A