Solved

T-SQL logic (data is not in table and is in table)

Posted on 2009-04-14
10
254 Views
Last Modified: 2012-05-06
Ok, I have some simple SQL code that is not working as expected.

I have 2 tables ([IVOS].[dbo].[claim] and ivos.dbo.iso_cs). I want to see if a claim_number is in the first table and not in the second.  Well, if I use the attached could, I get nothing returned.  This seems fine, but if I un-comment the NOT, then I get nothing returned.  But how can this be? The claim_number either is in the ivos.dbo.iso_cs or not in the ivos.dbo.iso_cs table, but the query returns nothing worth or not the NOT is used.
select claim_number

from 

[IVOS].[dbo].[claim]

where

claim_number = '2009102428'

and

claim_number   in (

select claim_number

from 

[IVOS].[dbo].[claim]

)
 
 

and

claim_number 

--NOT

  in (

select claim_number

from 

ivos.dbo.iso_cs

)

Open in new window

0
Comment
Question by:rmundkowsky
10 Comments
 
LVL 7

Expert Comment

by:nkhelashvili
ID: 24140409
select claim_number
from
[IVOS].[dbo].[claim]
where
claim_number
 not
  in (
select claim_number
from
ivos.dbo.iso_cs
)
0
 

Author Comment

by:rmundkowsky
ID: 24140620
Your code does not work either, granted I had to change it to this for the test:

   select claim_number
   from
   [IVOS].[dbo].[claim] as c
   where
      c.claim_number = '2009102428'
      and
        c.claim_number not in (
              select claim_number
              from
              ivos.dbo.iso_cs
        )




BTW, the following does return a value:

select claim_number
      from [IVOS].[dbo].[claim] as c
      where
      c.claim_number = '2009102428'
      and
      c.claim_number   in (
            select claim_number
                  from [IVOS].[dbo].[claim]
            )
0
 

Author Comment

by:rmundkowsky
ID: 24140654
Oh, I just found out that the server is running in SQLServer 2000 mode. I assume this may cause the query to not work.
0
 

Author Comment

by:rmundkowsky
ID: 24140776
This does work though:

select claim_number
      from [IVOS].[dbo].[claim] as c
      where
      c.claim_number = '2009102428'
      and
      c.claim_number   in (
            select claim_number
                  from [IVOS].[dbo].[claim] as b
where c.claim_number = b.claim_number
            )
      and
      c.claim_number  not  in (
            select claim_number
            from ivos.dbo.iso_cs as a
where c.claim_number = a.claim_number
            )
0
 
LVL 19

Expert Comment

by:folderol
ID: 24140837
This LEFT JOIN has the exact same results as using the IN construct, and performance should be better, although frequently not as good as if you used EXISTS, which I think you really were attempting, not IN.  The LEFT JOIN has the debug advantage (which is why I'm suggesting it) of returning evidence for or against a match without modification, since the column cs.claim_number will be null in the results if it doesn't exist, and then you can uncomment the last line.


select c.claim_number, cs.claim_number
from [IVOS].[dbo].[claim] as c
left outer join ivos.dbo.iso_cs as cs
on c.claim_number = cs.claim_number
where c.claim_number = '2009102428'
--and cs.claim_number is null
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

Author Comment

by:rmundkowsky
ID: 24141036
I agree that the way you have it coded is much more efficient.  But what I don't understand is why the code I presented does not return the correct result?

I mean, does SQL Server 2000 return incorrect answers if a query is too big or slow?
0
 
LVL 22

Accepted Solution

by:
dportas earned 500 total points
ID: 24141220
To take a generic example:

SELECT a
FROM t1
WHERE a NOT IN
 (SELECT b
  FROM t2);

If b contains a null then this query will always return zero rows, whether or not any a value exists in the b column. This is the correct result in standard SQL and in all versions of SQL Server. Therefore the NOT IN query is not equivalent to the apparently similar LEFT JOIN query or to a correlated query using NOT EXISTS. This is often overlooked by people who think EXISTS should work the same as IN. The fact that they are different is sometimes called the "EXISTS bug" because EXISTS always returns a TRUE or FALSE result whereas IN / NOT IN can be TRUE, FALSE or UNKNOWN.

The simplest answer is to modify your query with WHERE b IS NOT NULL:

SELECT a
FROM t1
WHERE a NOT IN
 (SELECT b
  FROM t2
  WHERE b IS NOT NULL);


0
 
LVL 21

Expert Comment

by:JestersGrind
ID: 24141242
Can claim_number be NULL in iso_cs?  If so, that is probably the issue that you're having.

From BOL:

Any null values returned by subquery or expression that are compared to test_expression using IN or NOT IN return UNKNOWN. Using null values in together with IN or NOT IN can produce unexpected results.

It's better to use EXISTS like the example below.

Greg



SELECT claim_number

FROM [IVOS].[dbo].[claim] as c

WHERE c.claim_number = '2009102428' 

AND NOT EXISTS(SELECT * FROM ivos.dbo.iso_cs as a

                WHERE c.claim_number = a.claim_number)

Open in new window

0
 

Author Comment

by:rmundkowsky
ID: 24141415
Wow, that sounds like the answer. Thanks all, I think Dportas nailed it, though the other inputs are helpful from a practical standing.

I guess the theoretical idea is that if NULL is in the set then the set is really larger than the set. So NULL is more than another value in the set that happens to be labeled NULL, but instead is kind of saying you can match against everything outside the set, but you still don't end out with a TRUE or FALSE.
0
 
LVL 22

Expert Comment

by:dportas
ID: 24141504
You are right that null doesn't behave like a regular value. Nulls aren't really values at all, they are a type of marker.

Unfortunately SQL isn't very consistent about how it uses nulls and its treatment of them is a long way from conventional logic, maths or even common sense. You just have to learn and remember the quirks of nulls. You can also try to avoid them as much as possible by making all your columns non-nullable but unfortunately they still crop up in some queries where you don't expect them.

0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
PL/SQL - Leading zeros 7 56
SQL query 4 46
Can Unique column have more than one Null? 8 43
SQl Server 2008 R2 - Case When Null still equals NULL 10 27
If you find yourself in this situation “I have used SELECT DISTINCT but I’m getting duplicates” then I'm sorry to say you are using the wrong SQL technique as it only does one thing which is: produces whole rows that are unique. If the results you a…
Composite queries are used to retrieve the results from joining multiple queries after applying any filters. UNION, INTERSECT, MINUS, and UNION ALL are some of the operators used to get certain desired results.​
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
A short film showing how OnPage and Connectwise integration works.

930 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now