简体   繁体   中英

What is the practical difference between these two SQL statements?

In an exam I was asked to retrieve the name of the transporters never having transported a container based in Rotterdam. The correct answer was

select  Transporter.ID 
from    Transporter
where   Transporter.ID not in (
   select TransporterID
   from   Container
   inner join Transportation on Container.ID = Transportation.ContainerID
   where Container.City = 'Rotterdam')

and nevertheless the following was marked as a wrong answer:

select  Transporter.ID 
from    Transporter
where   Transporter.ID in (
   select TransporterID
   from   Container
   inner join Transportation on Container.ID = Transportation.ContainerID
   where Container.City <> 'Rotterdam')

Why don't both statements lead to the same result? What is the practical difference between in ( ... where A <> B ) and not in ( ... where A = B ) ?

[Note that Transportation is in the center of the relational scheme, with all its prime attributs being foreign keys]

Let's build a simple table as example :

Container

TransporterID | City
 1            | 'Rotterdam'
 1            | 'Paris'
 2            | 'Rotterdam'

And then this query

SELECT TransporterID
FROM Container
WHERE Container.City <> 'Rotterdam'

This will result 1 (the row with paris)

Then, WHERE Transporter.ID IN ( ... statement will give wrong result (transporter 1 has been to 'Rotterdam')

Besides what the other answers point out, take NULL s into consideration:

If City is NULL both queries would treat the comparison as FALSE in their WHERE clause...

You version is answering a slightly different question: "What are the ids of transporters that have transported a container somewhere other than Rotterdam?".

As for the best answer, I would use not exists (which is material) and table aliases (more stylistic):

select t.ID 
from Transporter t
where not exists (select 1
                  from Container c join
                       Transportation tr
                       on c.ID = t.ContainerID
                  where tr.TransporterID = t.id and
                        c.City = 'Rotterdam'
                 );

NOT IN does not behave the way most people expect when any row in the subquery returns NULL (all rows are filtered out in that case). NOT EXISTS has the expected behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM