1. CTE 到底是什么
CTE 就是:
先把一小段查询结果,起个名字,临时存起来,后面接着用。
它的通常写法是
sql
WITH 名字 AS (
一段查询
)
SELECT *
FROM 名字
先写一个草稿表,再正式往下算
比如代码里有这个:
sql
WITH log_Share AS (
SELECT
`分类`,
SUM(COALESCE(`运费`,0)) / SUM(COALESCE(`付款金额`,0)) AS `运费占比`
FROM nm_mj_data.nm_business_level1_detail_order_wide_metrics_day_v1
WHERE `运费` > 0
GROUP BY `分类`
)
SELECT ...
FROM nm_mj_data.nm_business_level1_detail_order_wide_metrics_day_v1 a
LEFT JOIN log_Share
ON a.分类 = log_Share.分类
1.1 为什么要用 CTE
因为如果不用 CTE,你就会遇到两个问题:
第一,SQL 会很乱
你本来想做两件事:
先算每个分类的运费占比
再把这个运费占比 join 到主表里
如果全揉在一起,SQL 会特别难看。
第二,逻辑不清楚
用了 CTE 以后,SQL 就像分步骤写:
第一步:先做
log_Share第二步:再拿
log_Share去参与主查询这样你一眼就知道每层在干嘛。
1.2 可以把 CTE 理解成"临时小表"
注意,它不是数据库里永久存在的表。
它只是:
这一次 SQL 执行时,临时生成的一个结果集
SQL 跑完,它就没了。
所以它和真正建表不一样:
-
CREATE TABLE是真的建表,长期存在 -
WITH ... AS (...)是临时起个名字,只在当前这条 SQL 里有效
1.3 用生活例子给你解释
可以把 CTE 想成你做题时先打草稿。
比如你想算全班平均分,并找出高于平均分的人。
你不会直接一口气乱算,你会先:
草稿 1:先算平均分
"全班平均分 = 82 分"
草稿 2:再拿这个平均分去比较每个人
"张三 90 分,高于平均分"
这个"先算出来的草稿",就很像 CTE。
1.4 必须注意一个点
CTE 虽然像表,但它不是表,它更像:
-
临时结果
-
当前 SQL 内的小模块
-
带名字的中间步骤
所以你看到:
sql
WITH xxx AS (...)
你脑子里第一反应应该是:
"哦,这里是在先准备一份中间结果,后面要拿来继续算。"
2. CURRENT_DATE 和 CURDATE()的辨析
这两个在 MySQL 里可以理解成:
sql
CURRENT_DATE = CURDATE()
都表示"今天的日期"。
所以这两句效果一样:
sql
SELECT CURRENT_DATE;
SELECT CURDATE();
2.1 它们真正的区别是什么
区别主要不在"结果",而在"风格"和"兼容性"。
1)CURDATE()
这是 MySQL 很常见的写法。
长这样:
sql
CURDATE()
特点是:
-
更像普通函数
-
在 MySQL 里很常见
-
很多人一眼就知道是"当前日期"
2)CURRENT_DATE()
这是 更接近标准 SQL 的写法
长这样:
sql
CURRENT_DATE
有些数据库也支持:
sql
CURRENT_DATE()
特点是:
-
更偏标准 SQL 风格
-
某些数据库兼容性更好
-
看起来像"系统当前日期关键字"
2.2 现在最该怎么理解
你可以直接记:
在 MySQL 中
-
CURDATE() -
CURRENT_DATE
结果一样,用哪个都行。
2.3 那为什么有的人用 CURDATE(),有的人用 CURRENT_DATE
因为大家习惯不一样。
喜欢 CURDATE() 的人
觉得它更直观,像普通函数,写起来顺手。
喜欢 CURRENT_DATE 的人
觉得它更标准化,更像 SQL 规范写法。
3. 关于sql中的注释与缩进问题
3.1 注释
单行注释使用:# 或者 -- (但是更加推荐-- 空格一个 因为更通用 有些的sql不一定支持#的单行注释)
多行注释使用:/* ......*/
3.2 缩进问题
并不会存在像python一样需要严格的缩进语法,这个自己管理缩进是因为为了让人阅读更加的方便
4. DATE_SUB 到底是什么
DATE_SUB 的作用就是:
从一个日期里,减去一段时间
它的固定结构是:
你可以把它硬翻译成:
"把原日期减去某个时间间隔"
举个例子:
sql
DATE_SUB(CURDATE(), INTERVAL 2 MONTH)
4.1 要真正理解的核心
DATE_SUB 不是只和"今天"一起用。
它其实是一个通用函数:
给它一个日期,再告诉它要减去什么时间,它就返回减完后的日期。
sql
DATE_SUB('2026-03-16', INTERVAL 10 DAY)
意思是:
2026-03-16 往前减 10 天
结果:
2026-03-06
4.2 它的本质你可以记成一句话
sql
DATE_SUB(A, INTERVAL B C)
等于:
A - B个C
其中:
-
A= 原日期 -
B= 数量 -
C= 时间单位