#進階7:子查詢
/*
含義:
出現在其他語句中的select語句,稱爲子查詢或者內查詢
外部的查詢語句,稱爲主查詢或外查詢
分類:
按子查詢出現的位置:
select後面
僅僅支持標量子查詢
from後面
支持表子查詢
where或having後面(★)
標量子查詢 (單行)√
列子查詢 (多行)√
行子查詢
exists後面(相關子查詢)
表子查詢
按結果集的行列數不同:
標量子查詢(結果集只有一行一列)
列子查詢(結果集只有一列多行)
行子查詢(結果集只有一行多列)
表子查詢(結果集一般爲多行多列)
*/
#一、where或having後面
/*
1、標量子查詢(單行子查詢)
2、列子查詢(多行子查詢)
3、行子查詢(多行多列)
特點:
①子查詢放在小括號內
②子查詢一般放在條件的右側
③標量子查詢,一般搭配單行操作符使用
> < >= <= <>
列子查詢,一般搭配多行操作符的使用
in、any/some、all
④子查詢的執行優於主查詢的執行,主查詢的條件用到了子查詢的結果
*/
#1、標量子查詢
#案例1:誰的工資比Abel高?
#①查詢Abel的工資
SELECT salary
FROM employees
WHERE last_name ='Abel';
#②查詢員工的信息,滿足 salary>①的結果
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 department_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id = 50
);
#非法使用標量子查詢
#2、列子查詢(多行子查詢)
#案例1:返回location_id是1400或1700的部門中的所有員工的姓名
SELECT last_name
FROM employees
WHERE department_id IN(
SELECT department_id
FROM departments
WHERE location_id IN(1400,1700)
);
#案例2:返回其他部門中比job_id爲‘IT_PROG’部門任一工資低的員工的:工號、job_id以及salary
SELECT 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';
#案例2:返回其他部門中比job_id爲‘IT_PROG’部門所有工資低的員工的:工號、job_id以及salary
SELECT 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';
#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後面
/*
緊緊支持標量子查詢
*/
#案例1:查詢每個部門的員工個數
SELECT d.*,(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id = d.department_id
) 個數
FROM departments d;
#案例2:查詢員工號=102的部門名
SELECT (
SELECT department_name
FROM departments d
INNER JOIN employees e
ON d.department_id = e.department_id
WHERE e.employee_id = 102
) 部門名;
#三、from後面
#案例:查詢每個部門的平均工資的工資等級
/*
將子查詢結果充當一張表,要求必須起別名
*/
#四、exists後面(相關子查詢)
/*
語法:
exists(完整的查詢語句)
結果:
1或0
*/
SELECT EXISTS(SELECT employee_id FROM employees);
#案例1:查詢有員工的部門名
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE d.`department_id`=e.`department_id`
);
#練習題
#1、查詢和Zlotkey相同部門的員工姓名和工資
SELECT last_name,salary
FROM employees
WHERE department_id =(
SELECT department_id
FROM employees
WHERE last_name = 'Zlotkey'
);
#2、查詢工資比公司平均工資高的員工的員工號,姓名和工資
SELECT employee_id,last_name,salary
FROM employees
WHERE salary > (
SELECT AVG(salary)
FROM employees
);
#3、查詢各部門中工資比本部門平均工資高的員工的員工號,姓名和工資
SELECT employee_id,last_name,salary,department_id
FROM employees e1
WHERE salary > (
SELECT AVG(salary)
FROM employees e2
GROUP BY department_id
HAVING e1.`department_id`=e2.`department_id`
) ;
#4、查詢和姓名中包含字母u的員工在相同部門的員工的員工號和姓名
SELECT employee_id,last_name
FROM employees
WHERE department_id IN(
SELECT DISTINCT department_id
FROM employees
WHERE last_name LIKE '%u%'
);
#5、查詢在部門的location_id爲1700的部門工作的員工的員工號
SELECT employee_id
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id =1700
);
#6、查詢管理者是King的員工的姓名和工資
SELECT last_name,salary
FROM employees
WHERE manager_id IN(
SELECT employee_id
FROM employees
WHERE last_name = 'K_ing'
);
#7、查詢工資最高的員工的姓名,要求first_name和last_name顯示爲一列,列名爲姓,名
SELECT CONCAT(first_name,last_name) "姓.名"
FROM employees
WHERE salary = (
SELECT MAX(salary)
FROM employees
);