Search code examples
sqldatabaserelational-databaserelational-division

Converting From NOT EXISTS to NOT IN


I have three tables:

  • sailor (sname, rating);
  • boat (bname, color, rating);
  • reservation (sname, bname, weekday, start, finish);

In order to get a list of sailors who have reserved every red boat, I have:

select s.sname from sailor s 
where not exists(  
    select * from boat b  
    where b.color = 'red'  
    and not exists (  
        select * from reservation r  
        where r.bname = b.bname  
        and r.sname = s.sname));

I now need to rewrite this query with NOT IN instead of NOT EXISTS. Here's what I have so far:

select s.sname from sailor s
where s.sname not in (select s2.sname from sailor s2 where
    s2.sname not in (select r.sname from reservation r where r.bname not in (
            select b.bname from boat b where b.color <> 'red' )));

This, however, returns a list of all sailors who have reserved a red boat (not necessarily all of them). I'm having great difficulty checking whether or not a name in the list has reserved EVERY boat (I also cannot use COUNT()).

Any help is appreciated


Solution

  • Inorder to get a list of sailors who have reserved every boat. I'll use this script

    Solution 1:

     ;WITH k AS 
        (
        SELECT b.sname,COUNT(distinct a.bname) coun FROM boat a
        INNER JOIN reservation b 
            on a.bname = b.bname
        GROUP BY b.sname
        )
        SELECT k.sname FROM k WHERE coun = (select COUNT(*) FROM boat AS b)
    

    Solution 2:

    SELECT s.sname
    FROM   sailor AS s
    WHERE  s.sname NOT IN (SELECT DISTINCT a.sname
                           FROM   (SELECT s.sname,
                                          b.bname
                                   FROM   sailor AS s
                                          CROSS JOIN boat AS b
                                   WHERE  b.color = "Red") a
                           WHERE  a.sname + a.bname 
                                                NOT IN (SELECT r.sname + r.bname
                                                        FROM   reservation AS r
                                                        WHERE  r.sname IS NOT NULL
                                                                AND r.bname IS NOT NULL));