子查询

一、独立子查询

      子查询独立于外部查询:可以把子查询代码独立出来单独运行

        Customers表中原始数据如下:

      Orders表中原始数据如下:


      1.独立单值子查询(独立标量子查询)

         子查询返回的是单个值,而不是数据集

1 use edisondb;
2  select *
3  from customers as C
4  where C.custid=(
5 select O.custid
6 from Orders as O
7 where O.orderid=10248
8 );

        查询结果为:

 注:使用单值独立子查询时,一定要保证子查询返回的是单个值,而不是数据集;

       若返回的是数据集,则会出现如下状况:

1 use edisondb;
2  select *
3 from customers as C
4 where C.custid=(
5 select O.custid
6 from Orders as O
7 where O.orderid between 10248 and 10252
8 );

        查询出错提示:

      2.独立多值子查询

         子查询返回的是数据集

1 use edisondb;
2 select *
3 from customers as C
4 where C.custid IN(
5 select O.custid
6 from Orders as O
7 where O.orderid between 10248 and 10253
8 );

         查询结果为:

                              外部表行1

                          外部表行2

二、相关子查询=       。        + 独立子查询

                                 。

                          外部表行n

      相关子查询最基本的执行逻辑是:将外部表中的 “每一行” 逐行代入到子查询中   (理解相关子查询的关键)

1 use edisondb;
2  select *
3  from customers as C
4  where exists (
5 select *
6 from Orders as O
7 where O.custid=C.custid and (O.orderid between 10248 and 10252)
8 );

      查询结果如下: 

  执行步骤: a)取Customers表中的第一行数据

             

                 b)将“外部表”第一行的数据代入到子查询where条件中,并执行子查询,获取中间数据集

                      此时,子查询相当于执行如下语句:      

1 use edisondb;
2 select *
3 from Orders as O
4 where O.custid=86 and (O.orderid between 10248 and 10252);
                      获取的中间数据集如下:

                    

                 c)将子查询中获取的中间数据集,代入到外部查询的where条件中,决定是否返回外部表

                    第一行数据

                    该步骤中,要么返回第一行数据,要么返回空,而不是返回整张外部表的数据(不同于一般

                    的select *

                     

                      说明:如果外部查询where条件为true,返回该行数据;where条件为false,不返回任何内容。

                               也就是说,以上的所有操作都只是为了确定是否返回外部表的第一行数据

                 d)然后不断重复以上操作,得到了最终结果:

                     外部表中的每行都重复前面的操作,将每一行操作返回的数据集进行合并,得到最终结果 

                    

三、相关子查询与独立子查询之间的转换

       下面的“相关子查询”和“独立子查询”相互等价

       相关子查询:

1 use edisondb;
2  select *
3  from customers as C
4  where exists (
5 select *
6 from Orders as O
7 where O.custid=C.custid and (O.orderid between 10248 and 10252)
8 );

      独立子查询:

1 use edisondb;
2  select *
3  from customers as C
4  where C.custid in (
5 select O.custid
6 from Orders as O
7 where O.orderid between 10248 and 10252
8 );
9

     查询结果均为:

    “相关子查询”转“独立子查询”:

              将子查询中“外部表”的列上移至,外查询的where条件中 (需要改EXISTES为IN

    “独立子查询”“相关子查询”:

              将外查询where条件中“外部表”的列下移至,子查询的where条件中(需要改IN为EXISTS

注:EXISTS用于相关子查询中(使程序员重点关心,返回当前外部行的条件是否为真,而不考虑子查询中具体的列

      IN用于独立子查询中

附:子查询联接查询的选择

        返回结果位于不同表中的列时,使用联接查询;

                            同一张表中的列时,使用子查询。

       

原文地址:https://www.cnblogs.com/edisonfeng/p/2096403.html