MySQL進階7:子查詢

# 進階7:子查詢
/*
含義:
出現在其他語句中的select語句,稱爲子查詢或內查詢
外部的查詢語句,稱爲主查詢或外查詢

示例:
select frist_name from employees where
 department_id in(
 select department_id from departments
 where location+id=17000
 )
 
分類
按子查詢出現的位置:
		select 後面(只能放標量子查詢)
		from 後面(只支持表子查詢)
		where或having 後面(標量子查詢、列子查詢、行子查詢)
		exists 後面(又叫相關子查詢)(表子查詢)
按結果集的行列數不同:
	標量子查詢(結果類只有一列或一行)
	列子查詢(結果集只有一列多行)
	行子查詢(結果集可以有一行多列)
	表子查詢(結果集,一般爲多行多列)

*/

# 一、where或having後面
# 1.標量子查詢(單行子查詢)
# 2.列子查詢(多行子查詢)
# 3.行子查詢(多行多列)
/*
特點:
①子查詢放在小括號內
②子查詢一般放在條件的右側
③標量子查詢,一般搭配着單行操作符使用
> < >= <= = <>

列子查詢,一般搭配着多行操作符使用
IN、ANY/SOME、ALL

④子查詢的執行優先於主查詢的執行,主查詢的條件用到了子查詢的結果
*/

# 1.標量子查詢

# 案例1: 睡得工資比Abel高?
SELECT *
FROM employees
WHERE salary>
(
	SELECT salary
	FROM employees
	WHERE last_name='Abel'
);

# 案例2:返回job_id與141號員工相同的,salary比143號員工多的員工 姓名,job_id和工資

SELECT last_name,job_id,salary
FROM employees
WHERE job_id=
(
	SELECT job_id
	FROM employees
	WHERE employee_id=141
)
AND salary>(
	SELECT salary
	FROM employees
	WHERE employee_id=143
);

# 案例3:返回公司工資最少的員工的last_name,job_id\salary

SELECT last_name,job_id,salary
FROM employees
WHERE salary=(
	SELECT MIN(salary)
	FROM employees
);

# 案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資

SELECT employee_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT MIN(salary)
	FROM employees
	WHERE department_id=50
)

# 2.列子查詢
/*
返回多行
使用多行比較操作符

操作符		含義
IN/NOT IN	等於列表中的任意一個
ANY/SOME	和子查詢返回的某一個值比較
ALL		和子查詢返回的所有值比較


*/

# 案例1: 返回location_id是1400或1700的部門中的所有員工姓名


SELECT last_name
FROM employees
WHERE department_id IN(
	SELECT DISTINCT department_id
	FROM departments
	WHERE location_id IN(1400,1700)
);

# 案例2: 返回其他工種中比job_id爲'IT_PROG'工種任一員工的員工號、姓名、job_id以及salary

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ANY(
	SELECT DISTINCT salary
	FROM employees
	WHERE job_id='IT_PROG'
) AND job_id <>'IT_PROG';

# 或者

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
	SELECT DISTINCT MAX(salary)
	FROM employees
	WHERE job_id='IT_PROG'
) AND job_id <>'IT_PROG';

# 案例3: 返回其他工種中比job_id爲'IT_PROG'工種所有員工的員工號、姓名、job_id以及salary

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ALL(
	SELECT DISTINCT salary
	FROM employees
	WHERE job_id='IT_PROG'
) AND job_id <>'IT_PROG';

# 或者

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<(
	SELECT DISTINCT MIN(salary)
	FROM employees
	WHERE job_id='IT_PROG'
) AND job_id <>'IT_PROG';

# 3.行子查詢(結果集一行多列或多行多列)

# 案例:查詢員工編號最小並且工資最高的員工信息
# 以前的方法
SELECT *
FROM employees
WHERE employee_id=(
	SELECT MIN(employee_id)
	FROM employees
) AND salary=(
	SELECT MAX(salary)
	FROM employees
);

# 行子查詢(兩個或多個條件的規則相同)
SELECT *
FROM employees
WHERE (employee_id,salary)=(
	SELECT MIN(employee_id),MAX(salary)
	FROM employees
);

# 二、select後面
# 案例:查詢每個部門的員工個數
SELECT d.*,(
	SELECT COUNT(*)
	FROM employees AS e
	WHERE e.department_id=d.`department_id`
)
FROM departments AS d;

# 案例2: 查詢員工號=102的部門名
SELECT (
	SELECT department_name
	FROM departments AS d
	INNER JOIN employees AS e
	ON d.department_id=e.department_id
	WHERE e.employee_id=102
) AS 部門;

# 三、from後面
/*
將子查詢結果做成一張表,要求該表必須要取別名
*/
# 案例:查詢每個部門的平均工資的工資等級

SELECT ag_dep.*,g.`grade_level`
FROM(
	SELECT AVG(salary) AS ag,department_id
	FROM employees
	GROUP BY department_id
) AS ag_dep
INNER JOIN job_grades AS g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

# 四、exists後面(相關子查詢)
/*
語法:
exists(完整的查詢語句)
結果:
1或0
*/

# 案例1:查詢有員工的部門名
SELECT department_name
FROM departments AS d
WHERE EXISTS(
	SELECT *
	FROM employees AS e
	WHERE d.`department_id`=e.`department_id`
);

# 案例2:查詢沒有女朋友的男生信息

SELECT bo.*
FROM boys AS bo
WHERE bo.id NOT IN(
	SELECT boyfriend_id
	FROM beauty
)

SELECT bo.*
FROM boys AS bo
WHERE NOT EXISTS(
	SELECT boyfriend_id
	FROM beauty AS b
	WHERE bo.id=b.boyfriend_id
)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章