当前位置 主页 > 技术大全 >

    mysql子查询,让 SQL 语句更灵活

    栏目:技术大全 时间:2025-09-19 15:31


    MySQL 的子查询(Subquery)是嵌套在其他 SQL 语句中的查询,也称为内部查询,而包含子查询的语句称为外部查询。子查询可以让 SQL 语句更灵活,用于过滤、计算或生成临时数据。

    基本语法

    子查询通常放在在 SELECTINSERTUPDATEDELETE 等语句中,用括号 () 包裹:

    sql
    外部查询 (SELECTFROMWHERE 条件);
    
     

    子查询的常见用法

    1. 在 WHERE 子句中使用(过滤数据)

    子查询返回单个值或一组值,用于 WHERE 条件判断。

    示例 1:返回单个值(单行子查询)

    sql
    -- 查找与 ID=1 的用户同部门的其他用户
    SELECT name, department 
    FROM employees 
    WHERE department = (
      SELECT department FROM employees WHERE id = 1
    );
    
     

    示例 2:返回多个值(多行子查询)
    使用 INANYALL 等关键字:

    sql
    -- 查找在 "销售部" 或 "市场部" 的员工订单
    SELECT * FROM orders 
    WHERE employee_id IN (
      SELECT id FROM employees WHERE department IN ('销售部', '市场部')
    );
    
     

    2. 在 SELECT 子句中使用(作为列值)

    子查询返回单个值,作为主查询结果集中的一列。

    sql
    -- 查询每个用户的订单总数(子查询作为列)
    SELECT 
      id, 
      name,
      (SELECT COUNT(*) FROM orders WHERE user_id = users.id) AS order_count
    FROM users;
    
     

    3. 在 FROM 子句中使用(作为临时表)

    子查询返回结果集,作为主查询的数据源(需给子查询起别名)。

    sql
    -- 统计每个部门的平均工资及部门人数
    SELECT 
      dept_avg.department,
      dept_avg.avg_salary,
      dept_count.emp_count
    FROM 
      (SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department) AS dept_avg
    JOIN 
      (SELECT department, COUNT(*) AS emp_count FROM employees GROUP BY department) AS dept_count
    ON dept_avg.department = dept_count.department;
    
     

    4. 在 HAVING 子句中使用(分组过滤)

    sql
    -- 查找员工人数超过公司平均部门人数的部门
    SELECT department, COUNT(*) AS emp_count
    FROM employees
    GROUP BY department
    HAVING COUNT(*) > (
      SELECT AVG(emp_count) 
      FROM (SELECT COUNT(*) AS emp_count FROM employees GROUP BY department) AS dept_counts
    );
    
     

    5. 关联子查询(依赖外部查询)

    子查询中引用了外部查询的列,每行数据单独执行一次子查询。

    sql
    -- 查找每个部门中工资高于本部门平均工资的员工
    SELECT name, department, salary
    FROM employees e1
    WHERE salary > (
      SELECT AVG(salary) 
      FROM employees e2 
      WHERE e1.department = e2.department  -- 关联外部查询的部门
    );
    
     

    子查询的注意事项

    1. 性能问题:复杂的子查询(尤其是关联子查询)可能导致性能下降,可考虑用 JOIN 替代。
    2. 返回值限制
      • 若子查询用在 => 等比较符后,必须返回单个值(单行单列)。
      • 若用 IN,子查询可返回多行单列
    3. 可读性:嵌套过深的子查询(如 3 层以上)建议拆分或用 CTE(公用表表达式)优化。
    4. 关键字支持:部分子查询中不能使用 LIMITFOR UPDATE 等关键字。

    子查询 vs JOIN

    多数情况下,子查询和 JOIN 可以实现相同功能,但:

    • 子查询更直观,适合简单逻辑。
    • JOIN 通常性能更好,适合复杂关联查询。

    例如,前文的部门用户查询可用 JOIN 改写:

    sql
    SELECT e1.name, e1.department 
    FROM employees e1
    JOIN employees e2 ON e1.department = e2.department
    WHERE e2.id = 1 AND e1.id != 1;
    
     

    根据实际场景选择合适的方式,优先保证可读性和性能。
1分钟搞定MySQL部署!Docker最强实操指南,含所有常用命令和配置
忘记MySQL密码怎么办?别慌!用这一招跳过验证,轻松重置管理员权限
MySQL自增主键用完怎么办?从原理到实战,全面破解开发中的高频难题
MySQL权限混乱?这几个命令让你彻底理清用户清单与权限归属
你的数据库安全吗?读懂MySQL这几种日志,关键时刻能「救你一命」
MySQL性能上不去?八成是这里没配好!手把手教你搞定my.cnf核心配置
修改MySQL字段长度别乱来!这3个核心要点和1个致命陷阱,新手必看
MySQL单表卡爆怎么办?从策略到实战,一文掌握「分表」救命技巧
你的MySQL数据库为什么总是又慢又卡?掌握这五大优化法则,查询速度快十倍!(上篇)
你的MySQL数据库为什么总是又慢又卡?掌握这五大优化法则,查询速度快十倍!(下篇)