select sid
from S
where not exists(select *
                 from C
                 where not exists(select * 
                  from SC 
                  where cno=C.cno))
比如S表中SNO字段数据为1,2,3,对应的字段sid为甲乙丙,C表中字段数据为11,22,33
SNO和CNO为SC表的外键,在SC表中对应的字段数据分别是1,11  2,11 2,22 3,11 3,22 3,33
上面的字段是如何执行的,然后得到的S表中的SNO是,如何一步步执行....
比如
select Sid
from S
where exists(select *
             from SC
             where sno=S.sno AND cno='11')
他的执行过程应该是,先从S表中取出一个元组,用其中的sno去检查SC表,若存在这样的满足WHERE条件的元组,则去S表此元组的sid放到结果表.
因为第一个SQL语句有多层NOT EXIST,他的执行过程应该是?求高人指点

解决方案 »

  1.   

    首先感谢LS回复
    小弟初学SQL,请问如何查看数据库的执行计划...
      

  2.   

    select sid from S
    where not exists(select * from C
                      where not exists(select * from SC  
                                          where cno=C.cno))
    --你这种写法查出来只有两种结果,要么一个都查不出来,要么select出来全部。
    --如果sc表里有cno跟c表cno一样的,返回true,那么select s表的全部,否则相反
      

  3.   

    select sid
    from S
    where not exists(select *
      from C
      where not exists(select *  
    from SC  
    where cno=C.cno AND sno=S.sno))
    对不起楼上,由于写的比较快没来得及仔细检查,上面的SQL语句少写了一个WHERE条件应该是这样的...我主要想知道的SQL的执行过程中是如何一步一步处理的.数据库中的数据拿楼顶的数据.
      

  4.   

    楼主可以把这个SQL语句想象成双重否定
    NOT EXISTS就是不存在 得到的值是个BOOL值
    所以是先执行NOT EXISTS子查询的内容 再执行外面的语句
      

  5.   

    三张表嵌套,sc表作为c表的内表,sc和c查出来的集合作为s表的内表
    改成这样方便你理解select sid from s
    where not exists( select 1 from (select sc.sno from c,sc where c.cno=sc.cno) a 
                      where sno=s.sno)
      

  6.   

    非常感谢LS回复,其实我也觉得应该先执行里面的子查询的内容,可是给这个两重逻辑绕晕了,所以我才在下面给出一个小的数据,用实际数据来加深对执行过程的理解.
    比如没有楼顶贴中嵌套查询的那个,我知道是先取一个元组,SNO:1,SID:甲 ,把SNO传到SC里面对比,找到SC中有1,11的元组,所以甲返回结果集。然后取第二个元组,SNO:2,SID:乙……最后得出结果集甲乙丙。
    可是遇到这两个的逻辑,我就给绕到了…
      

  7.   

    额,感谢SSP2009的回复
    这样是方便理解了,可是用此SQL语句得到的结果和原来的不一样...
      

  8.   

    假如S表
    sid  sno
    甲    1
    乙    2
    丙    3
    C表
    cno
    11
    22
    33
    SC表
    sno cno
    1    11
    2    11
    2    22
    3    11
    3    22
    3    33
    执行过程是怎么样的,再顶一下
      

  9.   


    SELECT S.sid
    FROM S
    WHERE NOT EXISTS(
    SELECT *
    FROM C
    WHERE NOT EXISTS(
    SELECT *
    FROM SC
    WHERE SC.cno = C.cno
    AND SC.sno = S.sno
    )
    )查询S,使得不存在C,没有SC的组合。
    即:
    查询S,对于所有C都有SC的组合。
    代码可以写成:SELECT S.sid
    FROM S
    WHERE S.sno IN (
    SELECT SC.sno
    FROM SC
    INNER JOIN C
    ON SC.cno = C.cno
    GROUP BY SC.sno
    HAVING COUNT(*) = (SELECT COUNT(*) FROM C)
    )
      

  10.   

    不知道我这样分析对不对,
    第一步:查询分析器读到“select sid from S where not exists...”知道要完成这条语句得先得到not exists后面查询的值,这个值是一个真或者假.第二步:查询分析器读到“select * from C where not exists”知道要完成这条语句得先得到not exists后面查询的值,这个值是一个真或者假第三步:查询分析器读到“select * from SC where cno=C.cno AND sno=S.sno”,这时就开始连接SC表和C表(是否满足SC.cno = C.cno),如果不满足向则向第二步返回不存在(真),如果满足就继续连接SC表和S表(SC.sno=S.sno),如果不满足向则向第二步返回不存在(真),如果满足则返回第二步存在(假)第四步:如果第二步得到真,则执行“select * from C”返回所有记录,向第一步返回存在(假),如果假则不返回记录,向第一步返回不存在(真)第五步:第一步如果得到真,则执行 “select sid from S”,如果得到假则不执行,得到0条记录
      

  11.   


    --查询1
    SELECT S.sid
    FROM S
    WHERE NOT EXISTS(
        SELECT *
        FROM C
        WHERE NOT EXISTS(
            SELECT *
            FROM SC
            WHERE SC.cno = C.cno
                AND SC.sno = S.sno
        )
    )
    对于S表的(甲 1),判断如下查询2-1是否有结果,若没有结果则返回。
        --查询2-1
        SELECT *
        FROM C
        WHERE NOT EXISTS(
            SELECT *
            FROM SC
            WHERE SC.cno = C.cno
                AND SC.sno = 1
        )
        对于C表的11,SC表存在(1,11),不返回;
        对于C表的22,SC表不存在(1,22),返回;BREAK
        因为22返回,查询2-1有结果,所以查询1的(甲 1)不返回。
    对于S表的(丙 3), 判断如下查询2-3是否有结果,若没有结果则返回。
        --查询2-3
        SELECT *
        FROM C
        WHERE NOT EXISTS(
            SELECT *
            FROM SC
            WHERE SC.cno = C.cno
                AND SC.sno = 3
        )
        对于C表的11,SC表存在(3,11),不返回;
        对于C表的22,SC表存在(3,22),不返回;
        对于C表的33,SC表存在(3,33),不返回;
        因为查询2-3无结果,所以查询1的(丙 3)返回。
      

  12.   

    一层的相关子查询搞清楚了,多层的无非是嵌套而已。还是要从SQL的语义、即查询的逻辑处理过程入手来理解。否则数据量大了,你总不可能一条一条分析。