高级sql技巧

高级SQL技巧涵盖了多个方面,包括窗口函数、递归查询、公用表表达式(CTE)、子查询、集合操作等。

一、窗口函数

窗口函数允许用户在一组行(称为窗口)上执行计算,而不会将这些行合并成单个结果行。在处理排名、累计和运行总和等场景中非常有用。

案例

假设有一个员工表(employees),包含员工ID(employee_id)、部门ID(department_id)和薪水(salary)等字段。现在想要查询每个部门内员工的薪水排名、薪水等级(允许并列)和连续等级(不允许并列)。

复制代码
SELECT
    employee_id,
    department_id,
    salary,
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS row_num,
    RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank,
    DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dense_rank
FROM
    employees;

说明

  • ROW_NUMBER():为每个部门的员工按薪水降序分配一个唯一的序号。
  • RANK():为每个部门的员工按薪水降序分配一个等级,允许并列,并列后的等级会跳过。
  • DENSE_RANK():为每个部门的员工按薪水降序分配一个连续等级,不允许并列。

二、递归查询

递归查询允许用户在一个查询中多次引用同一个表,这在处理树形结构数据(如组织架构、目录结构)时非常有用。

案例

假设有一个员工表(employees),包含员工ID(employee_id)、经理ID(manager_id)等字段。现在想要查询每个员工的所有上级经理,直到最高级经理(没有经理的经理)。

复制代码
WITH RECURSIVE EmployeeCTE AS (
    SELECT
        employee_id,
        manager_id,
        1 AS level
    FROM
        employees
    WHERE
        manager_id IS NULL
    UNION ALL
    SELECT
        e.employee_id,
        e.manager_id,
        ecte.level + 1
    FROM
        employees e
    INNER JOIN
        EmployeeCTE ecte ON e.manager_id = ecte.employee_id
)
SELECT
    employee_id,
    manager_id,
    level
FROM
    EmployeeCTE
ORDER BY
    level,
    employee_id;

说明

  • WITH RECURSIVE EmployeeCTE AS (...):定义一个递归公用表表达式(CTE)。
  • 初始查询部分:选择最高级经理(没有经理的经理)。
  • 递归查询部分:通过内连接将员工表与CTE进行连接,查找每个员工的上级经理,并增加层级(level)。

三、公用表表达式(CTE)

CTE是一种临时的结果集,只在单个查询的执行周期内有效。它有助于使复杂查询更加易读和易维护。

案例

假设有一个销售表(sales),包含员工ID(employee_id)和销售金额(amount)等字段。现在想要查询总销售金额超过10000的员工ID和总销售金额。

复制代码
WITH SalesCTE AS (
    SELECT
        employee_id,
        SUM(amount) AS total_sales
    FROM
        sales
    GROUP BY
        employee_id
)
SELECT
    employee_id,
    total_sales
FROM
    SalesCTE
WHERE
    total_sales > 10000;

说明

  • WITH SalesCTE AS (...):定义一个公用表表达式(CTE),计算每个员工的总销售金额。
  • 在主查询中引用CTE,并筛选总销售金额超过10000的员工。

四、子查询

子查询是嵌套在另一个查询中的查询,常用于筛选条件和数据过滤。

案例

假设有一个员工表(employees),包含员工ID(employee_id)和薪水(salary)等字段。现在想要查询薪水高于公司平均薪水的员工ID和薪水。

复制代码
SELECT
    employee_id,
    salary
FROM
    employees
WHERE
    salary > (SELECT AVG(salary) FROM employees);

说明

  • 子查询 (SELECT AVG(salary) FROM employees):计算公司平均薪水。
  • 主查询筛选薪水高于平均薪水的员工。

五、集合操作

集合操作允许用户将两个或多个查询结果集进行合并或比较。常见的集合操作符包括UNION、INTERSECT和EXCEPT。

案例

假设有两个表:客户表(customers)和供应商表(suppliers),都包含姓名(name)字段。现在想要查询所有客户和供应商的姓名(去重),以及同时是客户和供应商的姓名,还有只是客户的姓名(不是供应商)。

复制代码
-- 合并两个查询结果集(去重)
SELECT name FROM customers
UNION
SELECT name FROM suppliers;

-- 找出两个查询结果集的交集
SELECT name FROM customers
INTERSECT
SELECT name FROM suppliers;

-- 找出只在第一个查询结果集中存在的记录
SELECT name FROM customers
EXCEPT
SELECT name FROM suppliers;

说明

  • UNION:合并两个查询结果集,并去除重复记录。
  • INTERSECT:找出两个查询结果集的交集,即同时出现在两个结果集中的记录,并去除重复记录。
  • EXCEPT:找出只在第一个查询结果集中存在的记录,即出现在第一个结果集中但不出现在第二个结果集中的记录,并去除重复记录。

总结

这些高级SQL技巧在实际应用中非常有用,能够帮助开发者更高效地处理复杂的数据查询和分析任务。

相关推荐
证榜样呀9 分钟前
2026 中专大数据技术专业可考的证书有哪些,必看!
大数据·sql
Codefengfeng17 分钟前
数据安全知识点速通
sql
自不量力的A同学29 分钟前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
Exquisite.31 分钟前
Mysql
数据库·mysql
全栈前端老曹1 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
R1nG8631 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
阿钱真强道1 小时前
12 JetLinks MQTT直连设备事件上报实战(继电器场景)
linux·服务器·网络·数据库·网络协议
逍遥德2 小时前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring
笨蛋不要掉眼泪2 小时前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap