MySQL中的子查詢用法

子查詢

導入知識
1.select字句的構成
select …
from …
where …
group by
having …
order by

子查詢

1.子查詢是什麼?
查詢裏面嵌套查詢,也就是select裏面還有select
select …(select)
from …(select)
where …(select)
group by
having …(select)
order by
嵌套的select字句可能出現在以上位置

2.子查詢語法
子查詢(inner query)先執行,然後執行主查詢(outer query)
子查詢返回的結果被用於外部查詢中
子查詢可出現在幾乎所有的SELECT子句中,如:SELECT子句、FROM子句、WHERE子句、ORDER BY子句、HAVING子句等
子查詢必須放在小括號中
子查詢一般放在比較操作符的右邊,以增強代碼可讀性

3.子查詢分類
不相關子查詢
子查詢中沒有使用到外部查詢的表中的任何列。先執行子查詢,然後執行外部查詢
相關子查詢(correlated subquery)
子查詢中使用到了外部查詢的表中的任何列。先執行外部查詢,然後執行子查詢
以上兩種類型之下又可以分爲:
行子查詢(row subquery):返回的結果集是 1 行 N 列
列子查詢(column subquery):返回的結果集是 N 行 1列
表子查詢(table subquery):返回的結果集是 N 行 N 列
標量子查詢(scalar subquery):返回1行1列一個值

標量子查詢
1.標量子查詢(scalar subquery):返回1行1列一個值
可以使用 = > < >= <= <> 操作符對子查詢的結果進行比較

2.那麼什麼時候會用到子查詢呢?
(1)我們在寫select字句時,發現需要寫多條select字句才能得到結果,並且這多條select字句之間有依賴關聯的關係,依賴關係一般書寫在select後邊和where後邊,這時我們就將多條select字句合起來寫。
例如:以兩條select字句爲例:第一個select字句依賴第二個select字句的執行結果,我們就將使用子查詢

示例1:(1)select name from PLAYERS where PLAYERNO=(select PLAYERNO from TEAMS where TEAMNO=1);
(2)select PLAYERNO from TEAMS where TEAMNO=1;
select name from PLAYERS where PLAYERNO=6;
(1)和(2)的結果是一樣的
在這裏插入圖片描述示例2:
SELECT playerno,name,joined - (SELECT joined FROM players WHERE playerno=104) year_interval
##標量子查詢,起了別名爲 year_interval
FROM players
WHERE playerno < 60;
語句釋義:對於編號小於60的球員,得到他們加入俱樂部的年份和104號球員加入俱樂部的年份之間的差值在這裏插入圖片描述示例3:
SELECT playerno,NAME
FROM players
WHERE birth_date < ( ##標量子查詢,小於,大於,等於等比較符一般在where後執行;+,-等運算符一般在where字句之前執行
SELECT birth_date
FROM players
WHERE leagueno=‘6524’);
語句釋義:查詢生日小於聯盟隊員編號爲9999的球員生日的球員的編號和姓名在這裏插入圖片描述
行子查詢(多列單行)
行子查詢(row subquery):返回的結果集是 1 行 N 列
使用行表達式進行比較,可以使用 = > < >= <= <> in操作符
示例:
SELECT name,sex,town,playerno ##查詢name列,sex列,town列和player列
FROM players
WHERE (sex,town) = (SELECT sex, town ##行子查詢,sex和town等於select的值
FROM players
WHERE playerno=104)
and playerno!=104 ##將等於104的過濾掉

語句示例:查詢和104號球員性別相同並且住在同一城市的球員的編號在這裏插入圖片描述列子查詢(單行多列)
1.列子查詢(column subquery):返回的結果集是 N 行 1列
2.必須使用 IN、ANY 和 ALL 操作符對子查詢返回的結果進行比較。其中, ANY 和 ALL 操作符不能單獨使用,其前面必須加上單行比較操作符= > < >= <= <>
3.<=all(結果集) 釋義爲小於等於所有的,也就是求最小的 此外還有<all,>all,>=all等

any(結果集) 釋義爲大於裏面任何一個即可,也就是大於最小的,此外還有<any,<=any,>=any等

4.什麼時候用到列子查詢??
(1)一個需求需要多個sql(select)
(2)幾個select之間需要互相依賴

示例1:
SELECT playerno,NAME
FROM PLAYERS
WHERE playerno IN ( ##playerno in(SELECT字句查詢到的單行多列數據)
SELECT playerno
FROM matches);

語句釋義:查詢至少參加了一場比賽的球員的編號和姓名
注:球員參加比賽表(matches表)裏只有球員編號,球員名字在球員表中,所以在查詢時會用到多個select語句,可以使用列子查詢

示例2:
SELECT playerno,NAME,birth_date
FROM PLAYERS
WHERE birth_date <=ALL ( ##<=all釋義爲小於等於所有的,後邊是一個多行一列的結果集
SELECT birth_date
FROM PLAYERS);
語句釋義:查詢那些最老的球員的編號、姓名和生日。最老的球員指的是出生日期小於等於 所有其它球員的球員

示例3:
SELECT playerno,NAME,birth_date
FROM players
WHERE birth_date >ANY (   ##大於結果集的任何一個
SELECT birth_date
FROM players);
語句釋義:查詢除了最老的球員之外,所有其它球員的編號、姓名和生日

5.注意:如果子查詢的結果集中有null值,使用>ALL 和not in操作符時,必須去掉子查詢結果集中的null值,否則查詢結果錯誤
我們可以在結果集中使用where語句將null值過濾掉
示例:
SELECT leagueno,playerno
FROM players
WHERE leagueno >=ALL (
SELECT leagueno
FROM players
WHERE leagueno IS NOT NULL); ##在結果集中使用where語句將null值過濾
在這裏插入圖片描述此外,在使用not in也是將結果集的null值過濾

表子查詢(多行多列)
1.表子查詢(table subquery):返回的結果集是 N 行 N 列
必須使用 IN、ANY 和 ALL 操作符對子查詢返回的結果進行比較
示例:
SELECT *
FROM committee_members
WHERE (begin_date,end_date) IN ( ##in後邊的結果集可以是一列多行,where後可以是多列,是表子查詢(多行多列)
SELECT begin_date,end_date
FROM committee_members
WHERE position=‘Secretary’);
語句釋義:在committee_members表中,得到任職日期和卸任日期與具有Secretary職位的一行相同的所有行

內聯視圖
用在from子句中的子查詢叫做內聯視圖(inline view)。它用作一個數據源,外部查詢再從其中檢索行
內聯視圖必須要定義別名,否則出錯
示例:
SELECT playerno
FROM (SELECT playerno,sex ##()裏面的我們稱爲內聯視圖
FROM players
WHERE playerno < 10) AS player10 ##as的作用是起別名,此外還要注意select和where
後的列名必須出現在子查詢中(該示例是PLAYERNO和sex)
WHERE sex=‘M’;
語句釋義:得到編號小於10的男性球員的編號

子查詢中再嵌套子查詢
示例:
SELECT playerno
FROM
(SELECT playerno, sex
FROM
(SELECT playerno, sex, joined
FROM
(SELECT playerno, sex, joined
FROM players
WHERE playerno > 10) great10
WHERE playerno < 100) less100
WHERE joined > 1980) joined1980
WHERE sex = ‘M’ ;

注:對於select字句來說,執行順序是先執行子查詢,子查詢裏又嵌套子查詢時,先執行最裏面的子查詢,例如上述示例先執行綠色,在執行黃色,在執行藍色,最後執行無顏色部分的select字句。

相關子查詢
1.相關子查詢(correlated subquery)
子查詢中使用到了外部查詢的表中的任何列。先執行外部查詢,然後執行子查詢

2.相關子查詢的執行步驟
1)、先執行外部查詢,得到的行叫做候選行
2)、使用某個候選行來執行子查詢
3)、使用子查詢的返回值來決定該候選行是出現在最終的結果集中還是被丟棄
4)、重複以上步驟2和3,將所有的候選行處理完畢,得到最終的結果

注:子查詢的where條件中有主查詢的列
示例:
SELECT matchno,playerno,teamno
FROM matches m ##別名m
WHERE playerno = (
SELECT playerno
FROM teams t ##別名t
WHERE playerno = m.playerno);
語句釋義:對於球隊的隊長參加的每場比賽,得到比賽編號、隊長編號和球隊編號
語句分析:就是拿着外查詢的結果去比較內查詢的結果,如果兩個結果相符,則保留結果,否則將結果摒棄

什麼時候使用相關子查詢?
(1)需要使用子查詢
(2)兩個子查詢都不能獨立執行

EXISTS操作符
1.該操作符專門判斷子查詢的結果集是否不爲空:如果不爲空則返回true,否則返回false
也就是exists操作符只考慮是否返回數據,而不考慮返回數據是什麼。
2.什麼時候用EXISTS操作符
(1)常用於相關子查詢
(2)需求中往往有至少的關鍵詞

示例:
SELECT NAME,initials ##initials表示首字母
FROM players p
WHERE EXISTS ( ##exists表示後邊的select語句是否返回數據
SELECT 1 ##如果是一行數據返回一個1,多行數據返回多個1
FROM penalties
WHERE playerno = p.playerno );
語句示例:得到那些至少支付了一次罰款的球員的名字和首字母
語句分析:就是拿着外查詢的結果去比較內查詢的結果,如果兩個結果相符,則保留結果,否則將結果摒棄

NOT EXISTS操作符
1.該操作符專門判斷子查詢的結果集是否不爲空:如果爲空則返回true,否則返回false,跟exists操作符相反

2.什麼時候使用NOT EXISTS操作符
(1)常用於相關子查詢
(2)需求中往往有”不是”關鍵字

示例:
SELECT NAME,initials
FROM players p
WHERE NOT EXISTS( ##如果返回數據是隊長,不返回數據則是不是隊長符合需求
SELECT 1
FROM teams
WHERE playerno = p.playerno );
語句釋義:得到那些不是隊長的球員的名字和首字母

總結:
子查詢先執行,執行完畢之後,再執行外邊的,從裏到外的執行結構
單行單列比較的時候 = (子查詢也得是單行單列)
單行多列比較的時候 = (子查詢也得是單行多列)
過濾列(單列) in (當子查詢是多行單列)
過濾列(多列) in (當子查詢是多行多列)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章