SQL語句(五)子查詢


一、子查詢含義

出現在其他語句中的select語句,稱為子查詢內查詢

二、子查詢分類

按子查詢的位置分

位置 支持的查詢
SELECT后面 支持標量子查詢
FROM后面 支持表子查詢
WHEREHAVING后面 支持標量子查詢列子查詢行子查詢
EXISTS后面 支持表子查詢

按結果集的行列數不同分

分類類型 結果集行數
標量子查詢 一行一列
列子查詢 一列多行
行子查詢 一行多列
表子查詢 多行多列

三、WHERE后面的子查詢

1. 標量子查詢

tips: 單行操作符(> < =等)只能搭配標量子查詢

查詢工資比Abel高的所有員工信息

①查詢Abel的工資

SELECT 	salary
FROM 	employees
WHERE 	last_name = 'Abel';

結果為單行單列

②查詢員工的信息,滿足salary>①

查詢公司工資最少的員工的last_name, job_id, salary
①查詢MIN(salary)

SELECT MIN(salary)
FROM employees;

②查詢符號這項工資的員工,salary=①

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

查詢job_id與141號員工相同salary比143號員工多的員工的姓名job_id工資
①141號員工的job_id

SELECT job_id
FROM employees
WHERE employee_id=141;

②143號員工的salary

SELECT salary
FROM employees
WHERE employee_id=143;

③ 結果集映射到last_name, job_id, salary,且滿足條件 job_id=①salary>②

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
);

2. 列子查詢(多行子查詢)

使用多行操作符:

  • IN/NOT IN
    • IN()等價於=ANY() NOT IN()等價於<>ALL()
  • ANY/SOME
  • ALL

返回location_id1400或1700的部門中的所有員工姓名

使用聯表查詢操作得到結果:

SELECT last_name
FROM departments d INNER JOIN employees e
	ON d.department_id = e.department_id
WHERE d.location_id IN (1400, 1700);

使用列子查詢得到結果:
①查詢location_id1400或1700的所有部門的編號

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

②查詢滿足部門編號在列表內的員工的姓名

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

查詢其他工種中的
job_idIT_PROG工種的任一員工工資低的
員工的:工號姓名

①獲取IT_PROG工種所有工資

SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'

②查詢其他部門中符合條件salary<min(①)的員工信息

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

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

查詢員工編號最小而且工資最高的員工信息
①查詢最小的員工編號

SELECT MIN(employee_id)
FROM employees;

②查詢員工的最高工資

SELECT MAX(salary)
FROM employees;

③查詢符合employee_id=①,salary=②的員工

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 department_name 部門名, COUNT(1) 員工數量
FROM employees e RIGHT JOIN departments d
	ON e.department_id = d.department_id
GROUP BY department_name

使用子查詢

SELECT department_id, department_name,(
	SELECT COUNT(1)
	FROM employees e
	WHERE e.department_id=d.department_id
) 對應員工數
FROM departments d;

在使用子查詢中,外部的表名的別名可以傳遞到子查詢中,例如上面的departments 表的別名d就傳遞到了子查詢中。

該子查詢可以理解為:

  1. 先獲取外層查詢的結果集
  2. 然后對結果集的每條記錄進行遍歷,將對應的參數填入到子查詢中得到單條記錄的結果拼接到新列中

五、FROM后面的子查詢

查詢每個部門的平均工資工資等級

①查詢每個部門的平均工資

SELECT AVG(salary) ag,department_id
FROM employees e
WHERE e.department_id IS NOT NULL
GROUP BY department_id;

②查詢對應的工資等級,連接①的結果集和job_grades

SELECT department_id, ag, grade_level
FROM (
	SELECT AVG(salary) ag,department_id
	FROM employees e
	WHERE e.department_id IS NOT NULL
	GROUP BY department_id
) ag_dep INNER JOIN job_grades j
	ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

即可以將子查詢的結果集作為一張表用於聯表查詢操作

六、EXISTS后面的子查詢

EXISTS語句的作用

EXISTS語句后的括號中填入一個子查詢語句,返回的結果為false(0)或true(1),分別代表查詢結果是否為空。

例:

SELECT EXISTS(SELECT employee_id FROM employees);
SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=30000);

簡單應用

查詢有員工部門名

SELECT department_name
FROM departments d
WHERE EXISTS(
	SELECT * 
	FROM employees e
	WHERE e.department_id = d.department_id
);

這里等價於IN

SELECT department_name
FROM departments d 
WHERE d.department_id IN(
	SELECT DISTINCT department_id
	FROM employees
);

查詢沒有女票男神信息

使用EXISTS語句

  1. 查詢男神信息
  2. 篩選條件:他沒有女票
    等價於beauty 表中沒有boyfriend_id為當前男生的記錄
    等價於beauty 表中boyfriend_id為當前男生的id的記錄不存在
SELECT *
FROM boys bo
WHERE NOT EXISTS(
	SELECT *
	FROM beauty b
	WHERE bo.id=b.boyfriend_id
);

使用IN完成相同的任務:

  1. 查詢男神信息
  2. 篩選條件:他沒有女票
    等價於當前男生的id不在beauty 表中boyfriend_id字段的集合中
SELECT * 
FROM boys b
WHERE b.id NOT IN(
	SELECT boyfriend_id
	FROM beauty
);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM