从NOT EXISTS转换为NOT IN

时间:2014-11-02 08:42:12

标签: sql database relational-database relational-division

我有三张桌子:

  • sailor(sname,rating);
  • boat(bname,颜色,评级);
  • reservation(sname,bname,weekday,start,finish);

为了获得保留每艘红船的水手名单,我有:

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));

我现在需要使用NOT IN而不是NOT EXISTS重写此查询。这就是我到目前为止所拥有的:

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' )));
然而,这会返回所有保留红船(不一定都是全部)的水手的清单。我很难检查列表中的名字是否保留了每条船(我也不能使用COUNT())。

感谢任何帮助

2 个答案:

答案 0 :(得分:4)

这很有趣;您可以在NOT EXISTS ( ... )替换IN ( ...)的同时维护句法结构(相关子查询):

SELECT s.sname from sailor s
WHERE 13 NOT IN (
    SELECT 13 FROM boat b
    WHERE b.color = 'red'
    AND 42 NOT IN (
        SELECT 42 from reservation r
        WHERE r.bname = b.bname
        AND r.sname = s.sname
       )
    );

答案 1 :(得分:0)

为了获得保留每艘船的水手名单。我将使用此脚本

解决方案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)

解决方案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));