当前位置: 首页 > news >正文

SQL入门:CET-简化复杂查询的利器

一、CET 的核心概念

CET(Common Table Expression,通用表表达式)是 SQL 中通过WITH关键字定义的临时结果集,仅在当前 SQL 语句的执行周期内有效,用于简化复杂查询逻辑。

本质与特性:
  • 临时性:不存储在磁盘,仅在查询执行时动态生成,执行结束后立即释放,避免资源占用。
  • 可读性:通过命名将复杂子查询模块化,让逻辑更直观(如UserOrders比嵌套子查询更易理解)。
  • 递归能力:支持递归查询(需RECURSIVE关键字),是处理树形结构(如组织架构)、序列生成的唯一简洁方式。
  • 作用域:仅在定义它的 SQL 语句中有效,无法被其他独立查询调用(区别于临时表)。

二、CET 的使用场景与语法

1. 非递归 CET(基础场景)

适用于将复杂查询拆分为多个临时结果集,避免多层嵌套,常见于多表关联、数据过滤、统计分析等场景。

(1)单 CET 语法
WITH 结果集名称 (列名1, 列名2, ...) -- 列名可选,默认继承子查询列名
AS (-- 子查询:生成临时结果集的逻辑SELECT 列1, 列2 FROM 表名 WHERE 过滤条件
)
-- 主查询:引用CET进行分析
SELECT * FROM 结果集名称;

示例:筛选 2024 年订单金额超 1000 的用户消费记录

WITH HighValueOrders (订单ID, 用户ID, 金额) AS (SELECT order_id, user_id, amountFROM ordersWHERE order_date >= '2024-01-01' AND amount > 1000
)
SELECT 用户ID, SUM(金额) AS 总消费 
FROM HighValueOrders 
GROUP BY 用户ID;
(2)多 CET 语法(逻辑串联)

多个 CET 用逗号分隔,后续 CET 可引用前面的 CET,实现逻辑分层。

示例:分析用户年度消费与复购情况

WITH 
-- 步骤1:筛选2024年订单
Year2024Orders AS (SELECT order_id, user_id, amount, order_dateFROM ordersWHERE order_date BETWEEN '2024-01-01' AND '2024-12-31'
),
-- 步骤2:统计用户年度总消费(引用步骤1)
UserTotalSpend AS (SELECT user_id, SUM(amount) AS total_spendFROM Year2024OrdersGROUP BY user_id
),
-- 步骤3:筛选复购用户(订单数≥2,引用步骤1)
RepeatUsers AS (SELECT user_id, COUNT(order_id) AS order_countFROM Year2024OrdersGROUP BY user_idHAVING COUNT(order_id) >= 2
)
-- 主查询:关联用户信息,输出结果
SELECT u.user_name, uts.total_spend, ru.order_count
FROM users u
JOIN UserTotalSpend uts ON u.user_id = uts.user_id
JOIN RepeatUsers ru ON u.user_id = ru.user_id;
2. 递归 CET(高级场景)

用于处理树形结构(如部门层级、分类关系)或序列生成(如日期序列),必须包含两部分:

  • 锚点成员:递归的起始数据(如顶级部门)。
  • 递归成员:引用自身 CET 的查询,定义层级关联逻辑(如子部门关联父部门),需用UNION ALL连接。
语法结构
WITH RECURSIVE 递归结果集名称 (列1, 列2, 层级列)
AS (-- 1. 锚点成员:起始数据(非递归查询)SELECT dept_id, dept_name, parent_id, 1 AS levelFROM departmentsWHERE parent_id = 0 -- 假设parent_id=0为顶级部门UNION ALL -- 必须用UNION ALL连接-- 2. 递归成员:引用自身,生成下一层数据SELECT d.dept_id, d.dept_name, d.parent_id, r.level + 1 AS levelFROM departments dJOIN 递归结果集名称 r ON d.parent_id = r.dept_id -- 子部门关联父部门
)
-- 主查询:获取所有层级数据
SELECT dept_name, level FROM 递归结果集名称 ORDER BY level;

示例:查询部门层级(含 3 级部门)

假设departments表数据:

dept_iddept_nameparent_id
1总部0
2技术部1
3研发组2
4测试组2
5产品部1

执行递归 CET 后结果:

dept_namelevel
总部1
技术部        2
产品部2
研发组3
测试组3

三、CET 与其他临时结果集的区别

特性CET(WITH 子句)子查询(嵌套 / 派生表)临时表(CREATE TEMP TABLE)
作用范围仅当前 SQL 语句有效仅所在查询块有效(如 FROM 子句会话内有效(可多查询复用)
可读性高(模块化命名)低(多层嵌套难理解)中(需单独定义)
递归能力支持(需 RECURSIVE)不支持不支持
性能(常规场景)与子查询相当(数据库优化)与 CET 相当略高(可建索引)
适用场景复杂查询拆解、递归逻辑简单嵌套查询需多次复用临时数据的场景

四、CET 的优化技巧

CET 的性能优化需结合数据库执行计划,核心目标是减少临时结果集的大小和计算复杂度。

1. 非递归 CET 优化
  • 提前过滤数据:在 CET 子查询中尽量通过WHERELIMIT等条件减少结果集行数,避免后续关联时处理冗余数据。

-- 优化前:CET返回所有订单,再过滤
WITH AllOrders AS (SELECT * FROM orders)
SELECT * FROM AllOrders WHERE amount > 1000;-- 优化后:CET内部直接过滤,结果集更小
WITH HighValueOrders AS (SELECT * FROM orders WHERE amount > 1000)
SELECT * FROM HighValueOrders;
  • 避免重复计算:将重复使用的计算逻辑(如SUM(amount))放入 CET,减少重复执行。

  • 合理使用索引:对 CET 子查询中WHEREJOIN涉及的字段(如order_dateuser_id)建立索引,加速筛选和关联。

2. 递归 CET 优化(重点)

递归查询容易因层级过深或数据量大导致性能问题,需针对性优化:

  • 限制最大层级:通过level < N避免无限递归(如WHERE level < 10),尤其适用于数据可能存在循环引用的场景(如A→B→A)。

  • 追踪路径避免重复:用字符串记录路径(如path = CONCAT(parent_path, ',', dept_id)),通过NOT LIKE排除已访问节点:

WITH RECURSIVE DeptTree AS (SELECT dept_id, parent_id, CAST(dept_id AS CHAR(100)) AS path FROM departments WHERE parent_id = 0UNION ALLSELECT d.dept_id, d.parent_id, CONCAT(t.path, ',', d.dept_id)FROM departments dJOIN DeptTree t ON d.parent_id = t.dept_idWHERE t.path NOT LIKE CONCAT('%', d.dept_id, '%') -- 排除已出现的节点
)
SELECT * FROM DeptTree;
  • 索引优化:对递归关联的字段(如parent_id)建立索引,加速子查询与 CET 的连接。

  • 拆分大递归:若层级超过 100 级,可拆分为多次小递归查询,避免单次递归占用过多内存。

五、常见问题与解决方案

  1. 递归 CET 报错 “列数不匹配”

    • 原因:锚点成员与递归成员返回的列数或数据类型不一致。
    • 解决:确保两部分列名、数量、类型完全一致(如锚点返回dept_id, level,递归也必须返回相同结构)。
  2. 递归查询陷入死循环

    • 原因:数据存在循环引用(如A.parent_id = B.dept_idB.parent_id = A.dept_id)。
    • 解决:通过level限制最大层级,或用路径追踪排除重复节点。
  3. CET 性能比子查询差

    • 原因:数据库优化器未正确识别 CET 逻辑,导致执行计划低效。
    • 解决:查看执行计划(如EXPLAIN ANALYZE),对关键字段加索引;复杂场景可尝试将 CET 改写为子查询对比性能。

六、总结

CET 是简化复杂 SQL 的核心工具,非递归 CET 适合拆解多层逻辑,递归 CET 则是处理树形结构的唯一高效方式。使用时需注意:

  • 优先通过命名和分层提升可读性;
  • 递归查询必须控制层级,避免死循环;
  • 结合索引和数据过滤优化性能,必要时通过执行计划分析瓶颈。
http://www.dtcms.com/a/491910.html

相关文章:

  • 零基础网站建设教学培训wordpress弹窗通知插件
  • 北京网络科技有限公司官网吴忠seo
  • 静态代理和动态代理
  • 深度学习论文: Pixel-Perfect Depth with Semantics-Prompted Diffusion Transformers
  • uni-app学习笔记(二)
  • 中国网站设计师广州最专业的网站建设
  • 怎么查看网站的ftp地址wordpress 文章引用
  • 基于JETSON+FPGA+GMSL相机 vs 传统工业相机:高动态范围与低延迟如何重塑机器感知视觉?
  • 物联网开发学习总结(5)—— 深入对比 TDengine、InfluxDB 和 TimescaleDB 三大主流时序数据库的性能表现
  • 网站pv统计方法深圳logo设计公司哪家好
  • 软件测试— 测试分类
  • 三井物产商品预测竞赛思路
  • 各省住房和城乡建设厅网站南宁公司做seo
  • 网站如何建数据库淘宝建设网站的理由
  • 网站建站建设价格怎么开通自己的微信小程序
  • 网站用户界面设计宁波网站建设服务商
  • 笔试强训(五)
  • 网站建设服务合同印花税做任务赚q红包的网站
  • 多媒体在网站开发的分析安装wordpress 500
  • Flask框架网站
  • 工业视觉网关:RK3576赋能多路检测与边缘AI
  • 鞋帽网站欣赏wordpress 文章公开编辑
  • 茂名营销网站开发室内设计学校大专
  • 网站备案 申请给网站写教案做课件一节课多少钱
  • 项目信息版本混乱,该如何统一
  • 使用Mathematica对Duffing方程进行非线性分析
  • 企业微信公众平台企业网站怎么搜索优化
  • Maya python重命名工具
  • 阜阳建设网站公司电话国内做进口的电商网站
  • 深入浅出 AES 加密算法与 Go 语言实战