Skip to content

子查询

查询里套查询->WHERE子查询->计算字段子查询

什么是子查询

一句话:查询里套查询

比如"找出工资比平均工资高的人"——你得先知道平均工资是多少,再拿它去比较。这就是两个步骤,但可以写在一句 SQL 里:

sql
SELECT name, salary
FROM users
WHERE salary > (SELECT AVG(salary) FROM users);
+--------+----------+
| name   | salary   |
+--------+----------+
| 李四   | 12000.00 |
| 赵六   | 15000.00 |
| 周八   | 11000.00 |
| 吴九   | 13000.00 |
+--------+----------+

执行顺序:MySQL 先跑括号里的 SELECT AVG(salary) FROM users 得到 9875,再跑外层 WHERE salary > 9875

📝 子查询总是从内往外执行。

WHERE 中的子查询

子查询最常和 WHERE 搭配,作为过滤条件的数据来源。

配合 IN

"找出和孙七在同一个城市的所有人":

sql
SELECT name, city
FROM users
WHERE city IN (
    SELECT city FROM users WHERE name = '孙七'
);

内层查出孙七的城市 → 北京,外层查出所有北京的人。

配合比较运算符

子查询配合 = > < 等,要求子查询只返回一个值

sql
-- 查工资最低的人
SELECT name, salary
FROM users
WHERE salary = (SELECT MIN(salary) FROM users);

SELECT MIN(salary) 返回单个值 6000,外层用 = 比较,没问题。

如果子查询返回多行,= 会报错——这时候改用 IN

多层嵌套

子查询可以套娃(但别套太深):

sql
-- 找出比"上海最高工资"还高的人
SELECT name, city, salary
FROM users
WHERE salary > (
    SELECT MAX(salary)
    FROM users
    WHERE city = '上海'
);

内层查到上海最高工资 12000,外层找出所有工资 > 12000 的人。

作为计算字段的子查询

子查询还可以放在 SELECT 里,每一行都执行一次:

sql
SELECT name,
       salary,
       (SELECT AVG(salary) FROM users) AS avg_all,
       salary - (SELECT AVG(salary) FROM users) AS diff
FROM users;
+--------+----------+----------+-----------+
| name   | salary   | avg_all  | diff      |
+--------+----------+----------+-----------+
| 张三   |  8000.00 | 9875.000 | -1875.000 |
| 李四   | 12000.00 | 9875.000 |  2125.000 |
| 王五   |  9500.00 | 9875.000 |  -375.000 |
| ...    |      ... |      ... |       ... |
+--------+----------+----------+-----------+

每个人的工资和平均工资一比,差距一目了然。

子查询的注意事项

只返回单列

子查询结果给外层用的时候,通常只能返回一列

sql
-- ✅ 返回单列
SELECT * FROM users WHERE city IN (SELECT city FROM users WHERE age > 30);

-- ❌ 返回多列会报错
SELECT * FROM users WHERE city IN (SELECT city, name FROM users);

性能方面

子查询每跑一次外层,内层可能就要重新执行一遍——特别是放在 SELECT 里的子查询,每行都跑一次

大数据量时,子查询可能变慢。很多子查询可以用 JOIN 替代(下两章讲),性能通常更好。

💡 不需过度担心,数据量小的时候(几十万行以内),子查询的性能完全可接受。

小结

子查询就是"查询里套查询",一个 SELECT 的结果作为另一个 SELECT 的输入:

  1. WHERE 里的子查询 — 最常见的用法,用查询结果做筛选条件
  2. 计算字段里的子查询 — 在 SELECT 里直接查另一个表的统计数据
  3. 子查询的局限 — 嵌套太深可读性差,大量数据时性能不如 JOIN
  4. 能用 JOIN 的也能用子查询 — 选读起来更清晰的那个

💡 子查询不难,关键是搞清楚"外层查什么、内层查什么"。下一章 JOIN 会让你在两者之间多一个选择。

自主练习

  1. 查所有工资高于公司平均工资的人
  2. 查和赵六年龄相同的人(排除赵六自己)
  3. 查所有工资低于上海最高工资的人
  4. 在 SELECT 里用子查询,显示每人工资与公司最低工资的差值

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8