SQL query question: SELECT ... NOT IN

I am sure making a silly mistake but I can't figure what:

In SQL Server 2005 I am trying select all customers except those who have made a reservation before 2 AM.

When I run this query:

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

I get 0 results.

But

SELECT idCustomer FROM reservations 

returns 152.000 results and the "NOT IN" part:

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

returns only 284 rows

2

7 Answers

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

Make sure your list parameter does not contain null values.

Here's an explanation:

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

is the same as:

WHERE NOT (field1 = 1 OR field1 = 2 OR field1 = 3 OR field1 = null) 
  • That last comparision evaluates to null.
  • That null is OR'd with the rest of the boolean expression, yielding null. (*)
  • null is negated, yielding null.
  • null is not true - the where clause only keeps true rows, so all rows are filtered.

(*) Edit: this explanation is pretty good, but I wish to address one thing to stave off future nit-picking. (TRUE OR NULL) would evaluate to TRUE. This is relevant if field1 = 3, for example. That TRUE value would be negated to FALSE and the row would be filtered.

2

It's always dangerous to have NULL in the IN list - it often behaves as expected for the IN but not for the 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

Given it's SQL 2005, you can also try this It's similar to Oracle's MINUS command (opposite of UNION)

But I would also suggest adding the DATEPART ( hour, insertDate) column for debug

SELECT idCustomer FROM reservations EXCEPT SELECT idCustomer FROM reservations WHERE DATEPART ( hour, insertDate) < 2 
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 

[Update: Added additional criteria to handle idCustomer being NULL, which was apparently the main issue the original poster had]

2

Sorry if I've missed the point, but wouldn't the following do what you want on it's own?

SELECT distinct idCustomer FROM reservations WHERE DATEPART(hour, insertDate) >= 2 
2
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'); 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like