6-SQL子查询
(1) 什么是關聯子查詢,什么是非關聯子查詢 (嵌套查詢)
子查詢從數據表中查詢了數據結果,如果這個數據結果只執行一次,然后這個數據結果作為主查詢的條件進行執行,那么這樣的子查詢叫做非關聯子查詢。
如果子查詢需要執行多次,即采用循環的方式,先從外部查詢開始,每次都傳入子查詢進行查詢,然后再將結果反饋給外部,這種嵌套的執行方式就稱為關聯子查詢。
哪個球員的身高最高,最高身高是多少,就可以采用子查詢的方式:
-- 非關聯子查詢示例
select player_name, height FROM player where height = (select max(height) from player);
首先通過select max(height) from player 得到最高身高這個數值,然后再將這個值在player表中匹配查找,看誰符合這個值,進行輸出。
查詢每個球隊中大于平均身高的球員有哪些,并顯示他們的球員姓名、身高以及所在球隊 ID。
-- 關聯子查詢示例
select player_name, height, team_id from player as a where height > (select avg(height) from player as b where a.team_id = b.team_id);
如果子查詢的執行依賴于外部查詢,通常情況下都是因為子查詢中的表用到了外部的表,并進行了條件關聯,因此每執行一次外部查詢,子查詢都要重新計算一次,這樣的子查詢就稱之為關聯子查詢
(2) EXISTS子查詢
想要看出場過的球員都有哪些,并且顯示他們的姓名、球員 ID 和球隊 ID。在這個統計中,是否出場是通過 player_score 這張表中的球員出場表現來統計的,如果某個球員在 player_score 中有出場記錄則代表他出場過,這里就使用到了 EXISTS 子查詢,
select player_name, player_id, team_id from player where exists (select player_id from player_score where player.player_id = player_score.player_id);
查詢球員不存在于player_score表中的數據
select player_name, player_id, team_id from player where not exists (select player_id from player_score where player.play_id = player_score.player_id);
(3) 集合比較子查詢-- 與另一個查詢結果集進行比較
主要查詢操作符及定義:
IN 判斷是否在集合中
ANY 需要與操作符一起使用,與子查詢返回的任何值做比較
ALL 需要與操作符一起使用,與子查詢返回的所有值做比較
SOME 實際上是ANY的別名,作用相同,一般嘗試用ANY
想要看出場過的球員都有哪些,并且顯示他們的姓名、球員 ID 和球隊 ID。
select player_name, player_id, team_id from player where player_id in (select player_id from player_score where player.player_id = player_score.player_id);
不難看出,IN操作符和EXISTS操作符的查詢結果是一致的,那么應該如何選擇IN和EXISTS?
SELECT * FROM A WHERE cc IN (SELECT cc FROM B)
SELECT * FROM A WHERE EXIST (SELECT cc FROM B WHERE B.cc=A.cc)
實際上在查詢過程中,在我們對 cc 列建立索引的情況下,我們還需要判斷表 A 和表 B 的大小。在這里例子當中,表 A 指的是 player 表,表 B 指的是 player_score 表。如果表 A 比表 B 大,那么 IN 子查詢的效率要比 EXIST 子查詢效率高,因為這時 B 表中如果對 cc 列進行了索引,那么 IN 子查詢的效率就會比較高。同樣,如果表 A 比表 B 小,那么使用 EXISTS 子查詢效率會更高,因為我們可以使用到 A 表中對 cc 列的索引,而不用從 B 中進行 cc 列的查詢。
ANY 和 ALL 都需要使用比較符,比較符包括了(>)(=)(<)(>=)(<=)和(<>)等。
查詢球員表中,比印第安納步行者(對應的 team_id 為 1002)中任何一個球員身高高的球員的信息,并且輸出他們的球員 ID、球員姓名和球員身高
select player_name, player_id, team_id, height from player where height > any (select height from player where team_id = 1002);
查詢比印第安納步行者(對應的 team_id 為 1002)中所有球員身高都高的球員的信息,并且輸出球員 ID、球員姓名和球員身高
select team_id, player_id, player_name, height from player where height > all (select height from player where team_id = 1002);
請注意:ANY、ALL 關鍵字必須與一個比較操作符一起使用。因為如果你不使用比較操作符,就起不到集合比較的作用,那么使用 ANY 和 ALL 就沒有任何意義
(4) 將子查詢作為計算字段
實際上子查詢也可以作為主查詢的計算字段。
查詢每個球隊的球員數,也就是對應 team 這張表,我需要查詢相同的 team_id 在 player 這張表中所有的球員數量是多少。
select team_name, (select count(*) from player where player.team_id = team.team_id) as player_num from team;
在 player 表中只有底特律活塞和印第安納步行者的球員數據,所以它們的 player_num 不為 0,而亞特蘭大老鷹的 player_num 等于 0。在查詢的時候,我將子查詢SELECT count(*) FROM player WHERE player.team_id = team.team_id作為了計算字段,通常我們需要給這個計算字段起一個別名,這里我用的是 player_num,因為子查詢的語句比較長,使用別名更容易理解。
查詢得到場均得分大于 20 的球員。場均得分從 player_score 表中獲取,同時你需要輸出球員的 ID、球員姓名以及所在球隊的 ID 信息
-- 使用IN
select team_id, player_id, player_name from player where player_id in (select player_id from player_score GROUP BY player_id HAVING(avg(score) > 20));
-- 使用EXISTS
select team_id, player_id, player_name from player where exists (select player_id from player_score GROUP BY player_id HAVING(avg(score) > 20) and player.player_id = player_score.player_id);
select team_id, player_id, player_name from player where exists (select player_id from player_score where player.player_id = player_score.player_id GROUP BY player_id HAVING avg(score) > 20);
-- 使用JOIN
SELECT
t2.player_id,
t2.player_name,
t2.team_id,
t3.v
FROM
player AS t2
JOIN (
SELECT
t1.player_id,
avg( t1.total ) AS v
FROM
(
SELECT
player_id,
sum( score ) AS total
FROM
player_score
WHERE
game_id IN ( SELECT game_id FROM player_score GROUP BY game_id )
GROUP BY
player_id #對球員分組,計算在每場比賽中的總分數
) AS t1
GROUP BY
t1.player_id #對球員分組,計算所參加比賽的平均數
HAVING
v > 20 #場均得分大于20
) AS t3 ON t2.player_id = t3.player_id;
1、我理解的場均得分大于20,第一場得了40分,第二場得了2分,場均為21分滿足條件
2、一場比賽中,球員可以出現多次
解析思路,先得出球員在每場比賽中的總分數,然后對球員分組,計算球員在所參加比賽中的平均數
總結
- 上一篇: angular js 公告墙
- 下一篇: 【ZT】Enhancement Fram