sql允許多層嵌套,子查詢是嵌套在其他查詢中的查詢。我們可以把子查詢當做一張表來看到,即外層語句可以把內嵌的查詢結果當做一張表使用。
子查詢查詢結果有三種情況
不返回查詢記錄。若子查詢不返回記錄則主查詢也不會有查詢記錄
查詢單行記錄。若子查詢返回的是單行記錄,則在主查詢中可以對該單行記錄使用比較運算符
查詢多行記錄。若子查詢返回多行記錄,則在主查詢中不能對該子查詢記錄使用比較運算符
條件比較
=,!=,<>,<,>,<=,>=,
any,some,all
is null,is not null
between x and y
in(list),not in(list)
exists(sub-query)
like _ ,%,escape ‘\‘ _\% escape ‘\’
子查詢常用方法
1、any 即任何一個 ,大都用大於或小於的時候
select * from emp e where e.sal > any(1000,2000,3000); --大於其中其中任何一個
select * from emp e where e.sal > any(select s.losal from salgrade s );--大於其中其中任何一個
2、some 一些,和any的用法相同,不過some大都用在 等於的時候
select * from emp e where e.sal = some(1000,2000,3000);--等於其中其中任何一個
select * from emp e where e.sal = some(select s.losal from salgrade s );--等於其中其中任何一個
3、all 所有,即同時滿足所有的
select * from emp e where e.sal > all(1000,2000,3000);--同時大於所有的
select * from emp e where e.sal > all(select s.losal from salgrade s );--同時大於所有的
4、in
select * from emp e where e.deptno in (10,20);
等同於 select * from emp e where e.deptno='10' or e.deptno='20';
所以當主表查詢數據量大,子查詢數據量少的情況使用in
5、exists
exists(sub-query 只要這里面能返回一條結果,整個表達式就為true)
select e1.* from emp e1 where exists( select 1 from dept d1 where (d1.deptno=10 or d1.deptno=20) and d1.deptno=e1.deptno);
當主查詢數據量小,子查詢數據量大的情況使用exists
In和exists的區別
執行效率上的比較
比如Select * from T1 where x in ( select y from T2 )
執行的過程相當於:
select *
from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y1 or t1.x = t2.y2 ....;
所以當子查詢數據量較大時執行效率會降低
select * from t1 where exists ( select null from t2 where y = x )
執行的過程相當於:
for x in ( select * from t1 )
loop
if ( exists ( select null from t2 where y = x.x )
then
OUTPUT THE RECORD
end if
end loop
表 T1 不可避免的要被完全掃描一遍
in 是把外表和內表作hash join,而exists是對外表作loop,每次loop再對內表進行查詢。
如果子查詢得出的結果集記錄較少,主查詢中的表較大且又有索引時應該用in,反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用exists。 其實我們區分in和exists主要是造成了驅動順序的改變(這是性能變化的關鍵),如果是exists,那么以外層表為驅動表,先被訪問,如果是IN,那么先執行子查詢,所以我們會以驅動表的快速返回為目標,那么就會考慮到索引及結果集的關系了 另外IN是不對NULL進行處理