出現在select語句中的select語句,稱之爲子查詢或內查詢。外部的select查詢語句,被稱爲主查詢或外查詢。子查詢按結果集的行列數不同分爲4種,標量子查詢、列子查詢、行子查詢、表子查詢。
標量子查詢 | 列子查詢 | 行子查詢 | 表子查詢 | |
---|---|---|---|---|
結果集 | 一行一列 | 一列多行 | 一行多列 | 一般爲多行多列 |
位置 | select/where/having後 | where/having後 | where/having後 | from/exists後面 |
子查詢的特點
1:子查詢放在小括號內。
2:子查詢一般放在條件的右側。
3:標量子查詢,一般搭配着單行單列操作符使用 >、<、>=、<=、=、<>、!=
4:列子查詢,一般搭配着多行操作符使用
in(not in):列表中的“任意一個”
any或者some:和子查詢返回的“某一個值”比較,比如a>some(10,20,30),a大於子查詢中任意一個即可,a大於子查詢中最小值即可,等同於a>min(10,20,30)。
all:和子查詢返回的“所有值”比較,比如a>all(10,20,30),a大於子查詢中所有值,換句話
說,a大於子查詢中最大值即可滿足查詢條件,等同於a>max(10,20,30);
5:子查詢的執行優先於主查詢執行,因爲主查詢的條件用到了子查詢的結果。
創建五張表,對下列表進行描述解釋
表名 | 描述 |
---|---|
departments | 部門表 |
employees | 員工信息表 |
jobs | 職位信息表 |
locations | 位置表 |
job_grades | 薪資等級表 |
select後面的子查詢
子查詢位於select後面的,僅僅支持標量子查詢。
示例:查詢每個部門員工個數
SELECT
a.*,
(SELECT count(*)
FROM employees b
WHERE b.department_id = a.department_id) AS 員工個數
FROM departments a;
from後面的子查詢
將子查詢的結果集充當一張表,要求必須起別名,否者這個表找不到。
然後將真實的表和子查詢結果表進行連接查詢。
示例:查詢每個部門平均工資的工資等級
-- 1:查詢每個部門的平均工資
SELECT department_id,avg(a.salary)
FROM employees a
GROUP BY a.department_id;
-- 2:查詢所有薪資等級
SELECT * FROM job_grades;
-- 3:將上面2個結果連接查詢,篩選條件:平均工資 between lowest_sal and highest_sal;
SELECT
t1.department_id,
sa AS '平均工資',
t2.grade_level
FROM
(SELECT department_id,avg(a.salary) sa FROM employees a
GROUP BY a.department_id) t1, job_grades t2
WHERE
t1.sa BETWEEN t2.lowest_sal AND t2.highest_sal;
查詢結果如下:
+---------------+--------------+-------------+
| department_id | 平均工資 | grade_level |
+---------------+--------------+-------------+
| NULL | 7000.000000 | C |
| 10 | 4400.000000 | B |
| 20 | 9500.000000 | C |
| 30 | 4150.000000 | B |
| 40 | 6500.000000 | C |
| 50 | 3475.555556 | B |
| 60 | 5760.000000 | B |
| 70 | 10000.000000 | D |
| 80 | 8955.882353 | C |
| 90 | 19333.333333 | E |
| 100 | 8600.000000 | C |
| 110 | 10150.000000 | D |
+---------------+--------------+-------------+
12 rows in set (0.00 sec)
where和having後面的子查詢
where或having後面,可以使用下面三種
1:標量子查詢(單行單列行子查詢)
2:列子查詢(單列多行子查詢)
3:行子查詢(一行多列)
標量子查詢
標量子查詢是單行單列的子查詢,查詢結果只有一行一列。
示例1:查詢誰的工資比Abel的高
/*①查詢abel的工資【改查詢是標量子查詢】*/
SELECT salary
FROM employees
WHERE last_name = 'Abel';
/*②查詢員工信息,滿足salary>①的結果*/
SELECT *
FROM employees a
WHERE a.salary > (SELECT salary
FROM employees
WHERE last_name = 'Abel');
示例2:查詢最低工資大於50號部門最低工資的部門id和其最低工資【having】
**
/*①查詢50號部門的最低工資*/
SELECT min(salary)
FROM employees
WHERE department_id = 50;
/*②查詢每個部門的最低工資*/
SELECT
min(salary),
department_id
FROM employees
GROUP BY department_id;
/*③在②的基礎上篩選,滿足min(salary)>①*/
SELECT
min(a.salary) minsalary,
department_id
FROM employees a
GROUP BY a.department_id
HAVING min(a.salary) > (SELECT min(salary)
FROM employees
WHERE department_id = 50);**
列子查詢
列子查詢是單列多行子查詢,需要搭配多行操作符使用:in(not in)、any/some、all。
爲了提升效率,最好去重一下distinct關鍵字。
示例:返回location_id是1400或1700的部門中的所有員工姓名
/*①查詢location_id是1400或1700的部門編號*/
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN (1400, 1700);
/*②查詢員工姓名,要求部門是①列表中的某一個*/
SELECT a.last_name
FROM employees a
WHERE a.department_id IN (SELECT DISTINCT department_id
FROM departments
WHERE location_id IN (1400, 1700));
行子查詢
子查詢結果集一行多列
示例:查詢員工編號最小並且工資最高的員工信息
SELECT *
FROM employees a
WHERE (a.employee_id, a.salary) = (SELECT
min(employee_id),
max(salary)
FROM employees);
exists後面的子查詢
1:語法:exists(完整的查詢語句)。
2: exists查詢結果:1或0,exists查詢的結果用來判斷子查詢的結果集中是否有值。
3:一般來說,能用exists的子查詢,絕對都能用in代替,所以exists用的少。
4: 和前面的查詢不同,這先執行主查詢,然後主查詢查詢的結果,再根據子查詢進行過濾,子查詢中涉及到主查詢中用到的字段,所以叫相關子查詢
簡單示例:
mysql> SELECT exists(SELECT employee_id
FROM employees
WHERE salary = 300000) AS 'exists返回1或者0';
+----------------------+
| exists返回1或者0 |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.00 sec)