以下是关于 SQL 进阶语法与复杂查询 的详细解析,涵盖 子查询、窗口函数、递归查询 的核心语法、应用场景与实战案例,帮助突破 SQL 高级技能瓶颈。


一、子查询(Subquery)

1. 定义

    子查询是嵌套在主查询的WHEREHAVINGSELECTFROM等子句中。它的执行逻辑是先执行子查询,得到一个结果集,然后将这个结果集用于主查询的进一步处理。

2. 分类

为了更清晰地展示不同查询的运用,下面使用 Kooboo 在线工具中的 DrawDB 数据库设计 展示具体的表结构和示例数据(数据表的sql文件于文章顶部):


  1. 标量子查询返回单个值(一行一列)
    • 概念:返回单一值(一行一列)的子查询。该值可以作为一个普通的标量值参与主查询的运算或比较
    • 使用场景:常用于在主查询中根据某个特定条件获取一个单一值
    • 示例
      -- 查询 HR 部门的所有员工
      SELECT employee_name
      FROM employees
      WHERE department_id = (
          SELECT department_id
          FROM departments
          WHERE department_name = 'HR'
      );
      
      -- 子查询SELECT department_id ~ 'HR'返回HR部门的department_id
      -- 主查询根据这个单一值筛选出属于该部门的员工。
  2. 行子查询返回一行(多列)

    • 概念:返回一行多列数据的子查询,主查询可以使用行比较运算符(如=<>等)来比较行子查询的结果。
    • 使用场景:当需要同时比较多个列的值时使用。例如,
    • 示例
      -- 找出与某个特定员工在多个属性上都相同的其他员工
      SELECT *
      FROM employees
      WHERE (department_id, salary) = (
          SELECT department_id, salary
          FROM employees
          WHERE employee_name = 'Alice'
      );
      
      -- 子查询返回Alice员工的department_id和salary组成的行
      -- 主查询找出具有相同department_id和salary的其他员工
  3. 列子查询:返回一列(多行)

    • 概念:返回一列多行数据的子查询。主查询通常会使用INANYALL等操作符与列子查询的结果进行比较。
    • 使用场景:当需要在主查询中筛选出符合多个值条件的记录时使用。
    • 示例
      -- 要找出工资高于某个部门部分员工工资的员工
      SELECT employee_name
      FROM employees
      WHERE salary > ANY (
          SELECT salary
          FROM employees
          WHERE department_id = (
              SELECT department_id
              FROM departments
              WHERE department_name = 'HR'
          )
      );
      
      -- 子查询返回HR部门所有员工的工资列,主查询筛选出工资高于该列中任意一个值的员工。
      -- ANY:满足条件的任意一个
  4. 表子查询返回多行多列(作为临时表)

    • 概念:返回多行多列数据的子查询,相当于一个临时表。主查询可以将表子查询的结果当作一个普通表来使用。
    • 使用场景:当需要对一个复杂查询的结果进行进一步处理时使用。
    • 示例
      -- 对一个分组统计的结果再进行筛选
      SELECT *
      FROM (
          SELECT department_id, AVG(salary) AS avg_salary
          FROM employees
          GROUP BY department_id
      ) AS dept_avg_salary
      WHERE avg_salary > 5000;
      
      -- GROUP BY:当数据进行分组
      • 必须用 GROUP BY 的情况:当需要按某列 / 多列将数据分组,对每个组分别进行聚合统计(如 “每个部门”“每个类别” 的汇总)。
      • 无需用 GROUP BY 的情况:当需要对全表数据进行单一的聚合统计(如 “所有数据的总和 / 平均值”)。

  • 掌握 SQL复杂子查询后→下一篇学习 复杂窗口函数查询

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐