使用子查詢(嵌套查詢)oop
一、查詢有一門及格的學生性能
select * from tbl_student s翻譯
where 60 < any(select score from tbl_grade g where s.snum =g.snum);排序
或索引
select * from tbl_student shash
where 60 < some(select score from tbl_grade g where s.snum = g.snum);for循環
any 、 some 、 all 區別效率
any表示子查詢返回值中的任意一個值(any是等於N個or語句)select
expr>any(單列多行子查詢),expr大於子查詢中任一返回值, 也就是隻要大於子查詢最小返回值就能夠了循環
some在此表示知足其中一個的意義,是用or串起來的比較從句。 some和any用法意義是同樣的。
all表示子查詢返回值中的全部值 (all是等於N個And語句)
expr>all(單列多行子查詢),expr大於子查詢中全部返回值,也就是必需要大於子查詢中最大返回值才行
1 、 in 子查詢
in 按子查詢返回值分爲:單行單列、多行單列、單行多列、多行多列
in 按是否與主錶鏈接分爲:相關子查詢、無關子查詢
1.1 、單行單列子查詢
查詢學生的成績,要求顯示學生的姓名
select (select sname from tbl_student s where s.snum=g.snum) as sname,
(select cname from tbl_course c where c.cnum=g.cnum) as cname,
score
from tbl_grade g
1.2 、多行單列子查詢
查詢男同窗的成績
select * from tbl_grade g
where snum in (select snum from tbl_student where sex=‘0’)
1.3 、單行多列或多行多列子查詢
查詢男同窗的成績
select * from tbl_grade g where (snum,’0’) in (select snum,sex from tbl_student)
1.4 、檢索學全了課程的學生
select * from student s where snum in(
select g.snum from tbl_grade g group by g.snum
having count(*) = (select count(*) from tbl_course)
)
1.5 、檢索沒學全課程的學生
select * from student s where snum in(
select g.snum from tbl_grade g group by g.snum
having count(*) < (select count(*) from tbl_course)
)
二、exists子查詢
只要子查詢找到一條記錄,結果就是true
2.1 、查詢選修過課程的學生
select * from tbl_student s
where exists (select * from tbl_grade where s.snum=g.snum)
2.2 、查詢沒有選修過 1 號課程的學生的信息
select * from tbl_student s
where not exists
(select * from tbl_grade g where g.cnum=1 and s.snum=g.snum)
2.3 、查詢男同窗的成績
select * from tbl_grade g
where exists (select * from tbl_student s where s.snum=g.snum and sex=‘0’)
2.4 、檢索學全了課程的學生
分析:不可能【找不到一門課,這麼課找不到成績】
select s.* from tbl_student s where not exists(
select * from tbl_course c where not exists(
select * from tbl_grade g where g.snum=s.snum and c.cnum=g.cnum
))
2.5 、檢索沒學全課程的學生
分析:可能【找到 一門課 找不到 成績】
select s.* from tbl_student s where exists(
select * from tbl_course c where not exists(
select * from tbl_grade g where g.snum=s.snum and c.cnum=g.cnum
))
in和exists區別
一、 in 是把外表和內表做 hash 鏈接
select * from tbl_grade g
where snum in (select snum from tbl_student where sex=‘0’)
二、 exists 是對外表做 loop 循環,每次 loop 循環再對內表進行查詢。
如select * from tbl_grade g
where exists (select * from tbl_student s where s.snum=g.snum and sex=‘0’)
可理解爲:
for(g : select * from tbl_grade) {
if(exists(select * from tbl_student s where s.snum=g.snum and sex=‘0’)) {
print g;
}
}
所以:
in:若是內表返回數據量太大,確定生成臨時表,並且會進行排序,效率很是低。
所以,適合內表返回數據量較小的狀況。
exists:外表確定是循環,若是外表數據量太大,也一樣效率低。
所以,適合內表返回數據量多的狀況。
使用exists能夠按以下思路,不然很差理解:
一、exists子查詢是找到即中止並返回true(找到),找不到返回false(找不到)
說明:不要去翻譯爲存在和不存在,把腦殼搞暈。
二、頭腦中創建for循環
三、exists首先執行外層查詢,再執行內層查詢,與IN相反。
若是not in返回至少一個null,那麼not in就返回flase,第一個表的數據行就不會顯示。
對於not exists,只是關心是否返回行,所以返回的不管是null仍是非null,都是true,只要有數據返回。
使用not in仍是not exists,不單單是功能上不一樣,並且在性能上也有很大的不一樣。NOT IN會騙過子查詢中所涉及表的索引。