语句 · 2026 年 6 月 3 日 · 10 分钟
用 CTE 把复杂问数拆成能读的几段
复杂问数不是不能写,是不能写成一团。WITH 把「合格订单」「按日汇总」「排名」分开,第四拍才有落点。公开纠错循环能工作,也是因为每一步的中间结果能被看见。CTE 就是给人看的中间结果。
一段只做一件事
过滤、聚合、排名,三段。
命名像中文
paid_orders 比 t1 有用。
中间结果也可以 LIMIT 看
拆开的好处是可以单独跑前两段。
一次完整的问法可以先写成下面这样:
先筛合格订单,再按城市汇总,再取前五。
落到语句上,草稿常常是:
WITH paid AS (
SELECT city, pay_amount
FROM orders
WHERE pay_time >= DATE '2026-03-01'
AND pay_time < DATE '2026-04-01'
AND pay_status = 'paid'
AND is_internal = 0
),
agg AS (
SELECT city, SUM(pay_amount) AS gmv
FROM paid
GROUP BY city
)
SELECT city, gmv
FROM agg
ORDER BY gmv DESC
LIMIT 5;
三段都可以单独解释。解释不了的那段,就是还没问清楚的那段。
语句是收据,默认只读
第一纪律是 SELECT。草稿里出现更新、删除、结构变更,整张收据作废。第二纪律是时间窗。大表没有时间条件,不跑。第三纪律是粒度。GROUP BY 的键必须和问题里的维度一一对应。
一对多关联会把头上的金额按明细复制,看起来像增长,其实是扇形。COUNT 和 COUNT DISTINCT 不是同一指标。NULL 不是 0。日期函数没有世界语,能写绝对区间就写绝对区间。
复杂逻辑用公共表表达式拆开。拆开是为了给人看中间结果。先对再快。用索引去救一条口径错误的语句,会把错误生产化。
读完这一辑可以做什么
把你最近一条问数语句拆成三段 WITH:过滤、聚合、排名。每一段单独跑。有一段解释不清,就回到提问,不要在语句里继续加花样。
解释不了的那一段 WITH,就是还没问清楚的部分。