SQL进阶——with

在 MySQL 中,WITH 关键字用于定义 公用表表达式(Common Table Expressions,CTE)。CTE 是一个临时的结果集,可以在一个查询中多次引用,通常用于简化复杂查询,提高可读性。

基础语法

WITH cte_name AS (
    -- 子查询
    SELECT ...
)
SELECT ...
FROM cte_name;
  • cte_name 是 CTE 的名称。
  • WITH 子句中定义的 CTE 可以在后续的 SELECTINSERTUPDATEDELETE 语句中使用。

示例 1:简单的 CTE

假设有一个 employees 表,我们想查询工资高于平均工资的员工:

WITH avg_salary AS (
    SELECT AVG(salary) AS avg_sal FROM employees
)
SELECT name, salary
FROM employees, avg_salary
WHERE salary > avg_sal;
  • avg_salary 是一个 CTE,计算了员工的平均工资。
  • 在主查询中,我们将 employees 表与 avg_salary CTE 进行连接,筛选出工资高于平均工资的员工。

示例 2:递归 CTE

CTE 还支持递归查询,常用于处理层次结构数据(如树形结构)。

假设有一个 categories 表,存储了分类及其父分类:

CREATE TABLE categories (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    parent_id INT
);

我们想查询某个分类及其所有子分类:

WITH RECURSIVE category_tree AS (
    -- 基础查询:选择根节点
    SELECT id, name, parent_id
    FROM categories
    WHERE id = 1  -- 假设根节点的 id 是 1

    UNION ALL

    -- 递归查询:选择子节点
    SELECT c.id, c.name, c.parent_id
    FROM categories c
    INNER JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree;
  • WITH RECURSIVE 定义了一个递归 CTE。
  • 基础查询选择根节点。
  • 递归部分通过 UNION ALL 不断将子节点添加到结果集中,直到没有更多的子节点。

示例 3:多个 CTE

可以在一个查询中定义多个 CTE,用逗号分隔:

WITH
    dept_stats AS (
        SELECT department_id, AVG(salary) AS avg_sal
        FROM employees
        GROUP BY department_id
    ),
    high_paid_employees AS (
        SELECT e.name, e.salary, e.department_id
        FROM employees e
        JOIN dept_stats ds ON e.department_id = ds.department_id
        WHERE e.salary > ds.avg_sal
    )
SELECT * FROM high_paid_employees;
  • dept_stats CTE 计算每个部门的平均工资。
  • high_paid_employees CTE 筛选出工资高于部门平均工资的员工。
  • 最后从 high_paid_employees 中选择数据。

示例 4:CTE 用于更新或删除

CTE 不仅可以用于 SELECT,还可以用于 UPDATEDELETE

假设我们想将工资低于平均工资的员工的工资增加 10%:

WITH avg_salary AS (
    SELECT AVG(salary) AS avg_sal FROM employees
)
UPDATE employees
SET salary = salary * 1.10
WHERE salary < (SELECT avg_sal FROM avg_salary);
  • avg_salary CTE 计算平均工资。
  • UPDATE 语句使用 CTE 的结果来更新符合条件的记录。

注意事项

  1. CTE 的作用范围:CTE 仅在定义它的查询中有效,查询结束后 CTE 就会被销毁。
  2. 性能:CTE 可以提高查询的可读性,但在某些情况下可能会影响性能(尤其是递归 CTE)。
  3. 递归深度:MySQL 对递归 CTE 的深度有限制,默认是 1000 层,可以通过 cte_max_recursion_depth 参数调整。

总结

  • WITH 关键字用于定义 CTE,简化复杂查询。
  • CTE 可以是普通的(非递归)或递归的。
  • CTE 可以用于 SELECTUPDATEDELETE 等操作。
  • 递归 CTE 适合处理层次结构数据(如树形结构)。
### 石榴姐 SQL 进阶 实战 技巧 专栏介绍 #### 背景与目标 该专栏由莫叫石榴姐撰写,专注于提升读者在实际项目中应用SQL的能力。通过一系列深入浅出的文章,帮助开发者掌握复杂的查询优化、数据分析以及高级功能的应用。 #### 主要内容概览 ##### 数据库性能调优案例分享 通过对具体业务场景下的数据库操作进行剖析,讲解如何编写高效的SQL语句以提高系统响应速度和资源利用率[^1]。 ##### 复杂查询构建方法论 介绍了多种复杂查询的设计思路和技术手段,包括但不限于窗口函数(Window Functions)、CTE(Common Table Expressions)等现代SQL特性,使学习者能够应对更为棘手的数据处理需求。 ##### 特定领域问题解决方案 针对不同行业的特殊要求提供了针对性强的技术方案,例如金融行业中的交易流水分析、电商网站的商品推荐算法实现等方面均有所涉猎。 ##### 高级统计学概念的实际运用 探讨了诸如线性回归置信区间的计算方式,在Oracle环境中可通过`REGR_SLOPE()`和`REGR_INTERCEPT()`函数轻松获取模型参数;进一步讨论了标准误的求解过程及其意义所在[^2]。 ##### 客户行为模式挖掘工具——RFM模型解析 阐述了基于最近一次消费(Recency),频率(Frequency),金额(Monetary Value)三个维度评估顾客价值的方法,并给出了具体的SQL脚本用于执行相应的计算逻辑[^3]。 ##### 日常办公自动化实例——员工考勤管理系统设计 围绕企业内部常见的人员签到记录管理展开论述,明确了有效打卡判定规则并给出了一套完整的SQL代码片段来满足这一应用场景的需求[^4]。 ```sql WITH first_punch AS ( SELECT emp_id, MIN(punch_time) OVER (PARTITION BY DATE_TRUNC('day', punch_time)) as morning_check_in FROM attendance_records ) SELECT DISTINCT ON (emp_id, date_trunc('day', morning_check_in)) emp_id, to_char(morning_check_in,'YYYY-MM-DD HH24:MI') "Morning Check In Time" FROM first_punch WHERE EXTRACT(HOUR FROM morning_check_in) BETWEEN 8 AND 9; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值