1. MySQL中的WITH子句概述
MySQL 8.0版本引入了WITH子句(Common Table Expressions,简称CTE),这个功能彻底改变了我们编写复杂SQL查询的方式。作为一名长期与MySQL打交道的开发者,我发现CTE就像给SQL装上了"临时视图"的利器,特别适合处理需要多次引用相同子查询的场景。
在实际项目中,我经常遇到需要反复JOIN同一个子查询的情况。在8.0之前,要么重复写冗长的子查询,要么创建临时表——前者让SQL难以维护,后者带来额外的I/O开销。CTE完美解决了这个痛点,它创建的临时结果集仅存在于当前查询生命周期内,既保持了代码整洁,又不会产生实际表操作的开销。
注意:CTE是MySQL 8.0+的专属特性,如果你还在使用5.7或更早版本,需要考虑升级或寻找替代方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础CTE用法解析
2.1 单次引用CTE
最基本的CTE语法结构如下:
sql复制WITH cte_name AS (
SELECT columns FROM table WHERE conditions
)
SELECT * FROM cte_name;
举个实际案例:假设我们有个电商数据库,需要统计每个品类下销量前十的商品。传统写法需要嵌套子查询,而使用CTE可以这样实现:
sql复制WITH top_products AS (
SELECT
category_id,
product_id,
SUM(quantity) AS total_sales
FROM order_items
GROUP BY category_id, product_id
ORDER BY total_sales DESC
)
SELECT
p.category_name,
p.product_name,
tp.total_sales
FROM top_products tp
JOIN products p ON tp.product_id = p.id
WHERE (
SELECT COUNT(*)
FROM top_products tp2
WHERE tp2.category_id = tp.category_id
AND tp2.total_sales >= tp.total_sales
) <= 10;
这种写法比嵌套子查询清晰多了,特别是当业务逻辑复杂时优势更加明显。
2.2 多次引用CTE
CTE真正的威力在于可以被主查询多次引用,而无需重复定义。比如我们要比较各品类销量前10与后10产品的平均价格差异:
sql复制WITH product_sales AS (
SELECT
category_id,
product_id,
SUM(quantity) AS sales_volume,
AVG(price) AS avg_price
FROM order_items
GROUP BY category_id, product_id
),
top_products AS (
SELECT * FROM product_sales
ORDER BY sales_volume DESC
LIMIT 10
),
bottom_products AS (
SELECT * FROM product_sales
ORDER BY sales_volume ASC
LIMIT 10
)
SELECT
'Top' AS product_type,
AVG(avg_price) AS average_price
FROM top_products
UNION
