
查询中的查询
SELECT AVG(salary)
FROM employee;
AVG(salary)
-----------
9832.00
SELECT emp_name AS "员工姓名", salary AS "月薪"
FROM employee
WHERE salary > 9832;
员工姓名|月薪
-------|--------
刘备 |30000.00
关羽 |26000.00
张飞 |24000.00
诸葛亮 |24000.00
孙尚香 |12000.00
赵云 |15000.00
法正 |10000.00
SELECT emp_name, salary
FROM employee
WHERE salary > ( SELECT AVG(salary) FROM employee );
标量子查询(Scalar Subquery),返回单个值(一行一列)的子查询。上面的示例就是一个标量子查询。
行子查询(Row Subquery),返回单个记录(一行多列)的子查询。标量子查询是行子查询的一个特例。
表子查询(Table Subquery),返回一个临时表(多行多列)的子查询。行子查询是表子查询的一个特例。
标量子查询
SELECT emp_name AS "员工姓名", salary AS "月薪",
salary - (SELECT AVG(salary) FROM employee) AS "差值"
FROM employee;
员工姓名|月薪 |差值
-------|--------|------------
刘备 |30000.00|20168.000000
关羽 |26000.00|16168.000000
张飞 |24000.00|14168.000000
...
行子查询
-- Oracle、MySQL、PostgreSQL 以及 SQLite
SELECT emp_name, dept_id, job_id
FROM employee
WHERE (dept_id, job_id) = (SELECT dept_id, job_id
FROM employee
WHERE emp_name = '孙乾')
AND emp_name != '孙乾';
emp_name|dept_id|job_id
--------|-------|------
庞统 | 5| 10
蒋琬 | 5| 10
黄权 | 5| 10
...
表子查询
WHERE 条件中的子查询
SELECT emp_name
FROM employee
WHERE job_id = (SELECT job_id
FROM employee
WHERE dept_id = 1);
SELECT emp_name
FROM employee
WHERE job_id IN (SELECT job_id
FROM employee
WHERE dept_id = 1);
emp_name
--------
刘备
关羽
张飞
ALL、ANY 运算符
-- Oracle、MySQL、Microsoft SQL Server 以及 PostgreSQL
SELECT emp_name AS "员工姓名", hire_date AS "入职日期"
FROM employee
WHERE hire_date >ALL (SELECT e.hire_date
FROM employee e
JOIN department d ON (d.dept_id = e.dept_id)
WHERE d.dept_name = '研发部');
员工姓名|入职日期
-------|----------
法正 |2017-04-09
庞统 |2017-06-06
蒋琬 |2018-01-28
...
-- Oracle、MySQL、Microsoft SQL Server 以及 PostgreSQL
SELECT emp_name AS "员工姓名", hire_date AS "入职日期"
FROM employee
WHERE hire_date =ALL (SELECT e.hire_date
FROM employee e
JOIN department d ON (d.dept_id = e.dept_id)
WHERE d.dept_name = '研发部'
);
-- Oracle
SELECT emp_name AS "员工姓名", salary AS "入职日期"
FROM employee
WHERE salary >ALL (10000, 15000, 20000);
-- Oracle、MySQL、Microsoft SQL Server 以及 PostgreSQL
SELECT emp_name
FROM employee
WHERE job_id =ANY (SELECT job_id
FROM employee
WHERE dept_id = 1);
-- Oracle、MySQL、Microsoft SQL Server 以及 PostgreSQL
SELECT emp_name
FROM employee
WHERE job_id !=ANY (SELECT job_id
FROM employee
WHERE dept_id = 1);
emp_name
--------
刘备
关羽
张飞
...
-- Oracle
SELECT emp_name
FROM employee
WHERE job_id !=ANY (1, 2, 2); -- 等价于 job_id != 1 OR job_id != 2
FROM 子句中的子查询
SELECT d.dept_name AS "部门名称",
ds.avg_salary AS "平均月薪"
FROM department d
LEFT JOIN (SELECT dept_id,
AVG(salary) AS avg_salary
FROM employee
GROUP BY dept_id) ds
ON (d.dept_id = ds.dept_id);
部门名称 |平均月薪
--------|------------
行政管理部|26666.666667
人力资源部|13166.666667
财务部 | 9000.000000
研发部 | 7577.777778
销售部 | 5012.500000
保卫部 |
-- MySQL、PostgreSQL 以及 SQLite
SELECT emp_name, salary
FROM employee
WHERE job_id IN (SELECT job_id
FROM job
WHERE max_salary >= 20000
ORDER BY job_id)
ORDER BY emp_name;
关联子查询
SELECT d.dept_name AS "部门名称",
(SELECT AVG(salary) AS avg_salary
FROM employee
WHERE dept_id = d.dept_id) AS "平均月薪"
FROM department d
ORDER BY d.dept_id;
SELECT d.dept_name AS "部门名称",
o.emp_name AS "员工姓名",
o.hire_date AS "入职日期"
FROM employee o
JOIN department d ON (d.dept_id = o.dept_id)
WHERE o.hire_date = (SELECT MIN(i.hire_date)
FROM employee i
WHERE i.dept_id = o.dept_id);
部门名称 |员工姓名|入职日期
--------|-------|----------
行政管理部|刘备 |2000-01-01
行政管理部|关羽 |2000-01-01
行政管理部|张飞 |2000-01-01
人力资源部|诸葛亮 |2006-03-15
财务部 |孙尚香 |2002-08-08
财务部 |孙丫鬟 |2002-08-08
研发部 |赵云 |2005-12-19
销售部 |法正 |2017-04-09
横向子查询
SELECT d.dept_name, t.max_salary
FROM department d
JOIN (SELECT MAX(e.salary) AS max_salary
FROM employee e
WHERE e.dept_id = d.dept_id) t;
-- Oracle、MySQL 以及 PostgreSQL
SELECT d.dept_name "部门名称", t.max_salary AS "最高月薪"
FROM department d
CROSS JOIN
LATERAL (SELECT MAX(e.salary) AS max_salary
FROM employee e
WHERE e.dept_id = d.dept_id) t;
部门名称 |最高月薪
--------|--------
行政管理部|30000.00
人力资源部|24000.00
财务部 |12000.00
研发部 |15000.00
销售部 |10000.00
保卫部 |
-- Microsoft SQL Server 和 Oracle
SELECT d.dept_name "部门名称", t.max_salary AS "最高月薪"
FROM department d
CROSS APPLY (SELECT MAX(e.salary) AS max_salary
FROM employee e
WHERE e.dept_id = d.dept_id) t;
EXISTS 运算符
SELECT d.dept_name AS "部门名称"
FROM department d
WHERE EXISTS (SELECT 1
FROM employee e
WHERE e.sex = '女'
AND e.dept_id = d.dept_id)
ORDER BY dept_name;
部门名称
-------
研发部
财务部
SELECT d.dept_name AS "部门名称"
FROM department d
WHERE NOT EXISTS (SELECT 1
FROM employee e
WHERE e.sex = '女'
AND e.dept_id = d.dept_id)
ORDER BY dept_name;
部门名称
-----
人力资源部
保卫部
行政管理部
销售部
SELECT d.dept_name
FROM department d
WHERE NOT EXISTS (SELECT NULL
FROM employee e
WHERE e.dept_id = d.dept_id
AND sex = '女');
部门名称
---------
行政管理部
人力资源部
销售部
保卫部
SELECT d.dept_name AS "部门名称"
FROM department d
WHERE d.dept_id NOT IN (3, 4, NULL);
SELECT d.dept_name AS "部门名称"
FROM department d
WHERE d.dept_id != 3
AND d.dept_id != 4
AND d.dept_id != NULL;