子查询
一、独立子查询
子查询独立于外部查询:可以把子查询代码独立出来单独运行
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用于独立子查询中
附:子查询和联接查询的选择
返回结果位于不同表中的列时,使用联接查询;
同一张表中的列时,使用子查询。