locked
Problem with IN and NOT IN RRS feed

  • Question

  • hey guys , I wrote this query with IN and NOT IN , but I received the same answer

     

    IF '16101769' IN (SELECT DISTINCT Outlet FROM current_authorization )
    	PRINT 'TRUE'
    ELSE
    	PRINT 'FALSE'
    

     

     

    IF '16101769' NOT IN (SELECT DISTINCT Outlet FROM current_authorization )
    	PRINT 'TRUE'
    ELSE
    	PRINT 'FALSE'

    In both cases I receive FALSE . why is that ? it whether exists or not .

    I looked the execution plan , Sql Engine implements it with a semi left join  with this condition :

     

    Outlet IS NULL OR Outlet = '16101769'
    
    I know I can solve this problem with IF EXISTS , I'm not looking for a solution ,

     

    I'm looking for the reason . can anyone help me ?

     


    Siavash Tadayon Nia - Iran , Tehran - Tel : +98 912 22 65 855


    Monday, October 24, 2011 12:34 PM

Answers

  • The NOT IN operator can be translated into a series of "non-equal" expressions used together with AND logical operators, e.g.:

    ...column1 NOT IN ('a', 'b', 'c')

    can be written as:

    ...column1 <> 'a' AND column1 <> 'b' AND column1 <> 'c'

    Therefore, whenever NULL value occurs as one of the values in parenthesis you get no rows (NULL compared to any value always returns false).

    To avoid such situations you can simply filter out NULLs:

    IF '16101769' NOT IN (SELECT DISTINCT Outlet FROM current_authorization WHERE Outlet IS NOT NULL)...


    Pawel Potasinski, SQL Server MVP My blog: http://sqlgeek.pl
    Monday, October 24, 2011 1:12 PM
  • Another alternative is to use a NOT EXISTS comparator rather than NOT IN:

    If NOT EXISTS(select outlet from current_Authorization where outlet = '16101769')

    This will help to avoid the NULL issues and the 3-state logic problem that goes with the NOT IN clause.  This issue can be generally avoided by avoiding the NOT IN operator and rather using the NOT EXISTS operator.


    Monday, October 24, 2011 1:17 PM
  • Is it possible that Outlet column contains NULLs in current_authorization table?
    Best Regards, Uri Dimant SQL Server MVP http://dimantdatabasesolutions.blogspot.com/ http://sqlblog.com/blogs/uri_dimant/
    • Proposed as answer by Naomi N Monday, October 24, 2011 1:49 PM
    • Marked as answer by Siavash Tadayon Nia Tuesday, October 25, 2011 8:10 AM
    Monday, October 24, 2011 1:03 PM
    Answerer
  • My best guess is that it is NULL values in the current_authorization table that are giving you confusing results.

    You cannot compare a value to a NULL value.

    Try chaging your query to

    IF '16101769' NOT IN (SELECT DISTINCT Outlet FROM current_authorization WHERE Outlet IS NOT NULL)
    PRINT 'TRUE'
    ELSE
    PRINT 'FALSE'

    This should give you the results you are looking for.

     

    HTH

    Paul Livengood


    Paul Livengood
    • Proposed as answer by Naomi N Monday, October 24, 2011 1:49 PM
    • Marked as answer by Siavash Tadayon Nia Tuesday, October 25, 2011 8:28 AM
    Monday, October 24, 2011 1:07 PM

All replies

  • Hi,
    I checked this getting different output.

    DECLARE @TestX TABLE
    (Val INT)
    
    INSERT INTO @TestX
    SELECT 16101769
    
    IF '16101769' IN (SELECT DISTINCT Val FROM @TestX )
    	PRINT 'TRUE'
    ELSE
        PRINT 'FALSE'
    
    

    Shatrughna.
    Monday, October 24, 2011 12:47 PM
  • Hi  Sam !
     
    Lets try to learn from below example;

    USE AdventureWorks
    GO
    
    IF '289' IN (SELECT DISTINCT EmployeeID FROM HumanResources.Employee)
     PRINT 'TRUE'
    ELSE
     PRINT 'FALSE'
    --TRUE
    USE AdventureWorks
    GO
    
    IF '289' NOT IN (SELECT DISTINCT EmployeeID FROM HumanResources.Employee)
     PRINT 'TRUE'
    ELSE
     PRINT 'FALSE'
    --FALSE
    
    

    I would prefer you to use CASE Expressionunlike using IF ESLE like doing VB Programming in
    MS SQL Server. We have CASE Expression in MS SQL Server and thats what Data Developers used.

    SELECT EmployeeID , CASE WHEN EmployeeID IN ('289') THEN 'TRUE' ELSE 'FALSE' END FROM HumanResources.Employee
    WHERE CASE WHEN EmployeeID IN ('289') THEN 'TRUE' ELSE 'FALSE' END  = 'TRUE'
    

    It would be better if you explain your requirement so we could suggest you more better solution.

     
    Please let me know if this doesn’t work for you. Hope I have answered you correctly.
     
    Thanks, Hasham

     

    Monday, October 24, 2011 1:01 PM
    Answerer
  • Is it possible that Outlet column contains NULLs in current_authorization table?
    Best Regards, Uri Dimant SQL Server MVP http://dimantdatabasesolutions.blogspot.com/ http://sqlblog.com/blogs/uri_dimant/
    • Proposed as answer by Naomi N Monday, October 24, 2011 1:49 PM
    • Marked as answer by Siavash Tadayon Nia Tuesday, October 25, 2011 8:10 AM
    Monday, October 24, 2011 1:03 PM
    Answerer
  • My best guess is that it is NULL values in the current_authorization table that are giving you confusing results.

    You cannot compare a value to a NULL value.

    Try chaging your query to

    IF '16101769' NOT IN (SELECT DISTINCT Outlet FROM current_authorization WHERE Outlet IS NOT NULL)
    PRINT 'TRUE'
    ELSE
    PRINT 'FALSE'

    This should give you the results you are looking for.

     

    HTH

    Paul Livengood


    Paul Livengood
    • Proposed as answer by Naomi N Monday, October 24, 2011 1:49 PM
    • Marked as answer by Siavash Tadayon Nia Tuesday, October 25, 2011 8:28 AM
    Monday, October 24, 2011 1:07 PM
  • The NOT IN operator can be translated into a series of "non-equal" expressions used together with AND logical operators, e.g.:

    ...column1 NOT IN ('a', 'b', 'c')

    can be written as:

    ...column1 <> 'a' AND column1 <> 'b' AND column1 <> 'c'

    Therefore, whenever NULL value occurs as one of the values in parenthesis you get no rows (NULL compared to any value always returns false).

    To avoid such situations you can simply filter out NULLs:

    IF '16101769' NOT IN (SELECT DISTINCT Outlet FROM current_authorization WHERE Outlet IS NOT NULL)...


    Pawel Potasinski, SQL Server MVP My blog: http://sqlgeek.pl
    Monday, October 24, 2011 1:12 PM
  • Another alternative is to use a NOT EXISTS comparator rather than NOT IN:

    If NOT EXISTS(select outlet from current_Authorization where outlet = '16101769')

    This will help to avoid the NULL issues and the 3-state logic problem that goes with the NOT IN clause.  This issue can be generally avoided by avoiding the NOT IN operator and rather using the NOT EXISTS operator.


    Monday, October 24, 2011 1:17 PM
  • There is a good blog explaining the problem with IN/NOT IN in details:

    Why you should never use IN/NOT IN in SQL
    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog
    Monday, October 24, 2011 1:50 PM