回 帖 发 新 帖 刷新版面

主题:sql嵌套语句怎样执行?

select 名称 as 供应商名称 from 供应商表
where not exists 
(select * from 零件表
where not exists 
(select * from 供应表
where  供应商编号=供应商表.供应商编号 and 零件编号=零件表.零件编号))

是不是先执行
select * from 零件表
where not exists 
(select * from 供应表
where 零件编号=零件表.零件编号)
得到的结果为空

后执行
select 名称 as 供应商名称 from 供应商表
where not exists ......


可整个语句却能得到准确的结果


这语句到底是怎么执行的啊

回复列表 (共7个回复)

沙发

for(int i=0;i<n1;i++)
  for(int j=0;j<n2;j++)
    for(int k=0;k<n3;k++){
      int l=i+j+k;
    }
  }
}
类似上面的表达式的执行过程,其中i,j,k是各自的表里的记录,你自己琢磨一下吧。。。。

板凳

大哥

你的意思也就是先执行里面的

可是就是我上面说的啊

第一个执行的结果为空啊

3 楼

是不是先执行
select * from 零件表
where not exists 
(select * from 供应表
where 零件编号=零件表.零件编号)
得到的结果为空

后执行
select 名称 as 供应商名称 from 供应商表
where not exists ......
=======================
因为用的是not exists
如果结果为空
就执行
select 名称 as 供应商名称 from 供应商表

如果用的是exists
就相反
如果结果不为空
就执行外面的语句

4 楼

着我知道,关键是结果怎么会是,

"提供了所有零件的供应商名称"

5 楼

着我知道,关键是结果怎么会是,

"提供了所有零件的供应商名称"

我想不通啊

6 楼

这是个典型的相关子查询。所谓相关,是指子查询引用了上层表的数据。

为了说明其执行过程,简单起见,先看一个只有二层的,以上面的表为例子,下面这个SQL语句查询的是,还没有任何供应商供应的零件清单。

select * 
from 零件表
where not exists 
    (select * 
     from 供应表
     where  零件编号=零件表.零件编号)

执行过程逻辑上如下

   1.  open 零件表, 设置一个扫描游标 C1
   2.  if EOF(C1) then goto 6    //如果取完了则结束
       else  fetch C1 into  x    //取得一行零件数据,设为 x
   3.  open 供应表, 设置一个扫描游标 C2
   4.  if EOF(C2) then          //如果取完,则表示没有找到相等的记录,
       insert x into R;    //把x插入结果集合R
       close C2;
           goto 2;              //继续扫描零件表
       else  fetch C2 into y     //取得一行供应商数据,设为 y
   5.  if x.零件编号 == y.零件编号 then  
           close C2;      //找到相等记录,继续处理零件表
           goto 2;
       else
       goto 4         //继续扫描供应表
   6.  close C1
   7.  返回 R
       
对于3层及更多层的相关子查询,也是类似的处理方式,只不过相应需要同时处理的表更多。

希望这么表达能对楼主有所帮助!

7 楼



对于查询的子查询,先计算内层的子查询得到一个结果集合,再计算外层,如

求"供应商编号"为 10 的供应商所供应的零件清单:

SELECT *
FROM   零件表
WHEERe 零件编号 in 
    ( SELECT 零件编号
      FROM   供应表
      WHERE  供应商编号 = 10)


但是对于EXISTS/NOT EXISTS谓词的相关子查询,不能先算里面的,再算外面的;而是必须一起算,而且是以外层为主导驱动。

下面把楼主的原始语句执行逻辑写一遍;实际的数据库管理系统采用更优化的等价算法:


R = NIL;                 // 初始设置结果集合为空集
open 供应商表 as C1;     //准备扫描,设置游标C1
while not EOF(C1) do     //依次扫描C1
begin
    fetch C1 into x;      //取一行供应商表记录
    
    R1 = NIL;             //初始化临时结果集,用于存放零件表记录
    open  零件表 as C2;   //准备扫描,设置游标C2
    while not EOF(c2) do  //依次扫描C2
    begin
        fetch C2 into y; //取一行零件表记录
         
        R2 = NIL;        //初始化临时结果集,用于存放供应表记录
        open 供应表 as C3; //准备扫描,设置游标C3
        while not EOF(c3) do
        begin
            fetch C3 into z;
            if (z.供应商编号 == x.供应商编号 
                  and z.零件编号 = y.零件编号) then
            begin                    //找到符合条件的记录
                insert z into R2;    //插入临时表
                break;               //对于(NOT) EXISTS, 找到一条即可
      end;
        end;

        close C3;
        if R2 is NIL then       //第3层没找到过符合条件的?(NOT EXISTS)
        begin
            insert into y into R1;   //插入临时表
            break;                //找到一条即可       
        end;
    end;

    close C2;
    if R1 is NIL then          //第2层没找到过符合条件的?(NOT EXISTS)
    begin
        insert into x into R1;      //插入最终结果集合
    end;
end;

close C1;

return R;                           //得到结果


我来回复

您尚未登录,请登录后再回复。点此登录或注册