语句 · 2026 年 5 月 30 日 · 10 分钟
窗口函数:排名、累计、占比
窗口函数让排名、累计、占比变得好写。它不合并行,所以粒度还在。问数里我只用三种:ROW_NUMBER / RANK、SUM() OVER 做累计、SUM() OVER 做占比。更花的窗口,先问是不是真的需要。
排名先定并列哲学
见 Top N 那一篇。
累计要有排序键
没有 ORDER BY 的累计没有意义。
占比的分母
是全国还是组内,PARTITION BY 决定。不写分区,就是全体。
一次完整的问法可以先写成下面这样:
3 月各城市已支付 GMV 及占全部城市合计的比例。
落到语句上,草稿常常是:
SELECT
city,
SUM(pay_amount) AS gmv,
SUM(pay_amount) * 1.0 / SUM(SUM(pay_amount)) OVER () AS share
FROM orders
WHERE pay_time >= DATE '2026-03-01'
AND pay_time < DATE '2026-04-01'
AND pay_status = 'paid'
GROUP BY city
ORDER BY gmv DESC;
占比写出来以后,把合计加总是否为 1 看一眼。不是 1,就去找过滤和空值。
语句是收据,默认只读
第一纪律是 SELECT。草稿里出现更新、删除、结构变更,整张收据作废。第二纪律是时间窗。大表没有时间条件,不跑。第三纪律是粒度。GROUP BY 的键必须和问题里的维度一一对应。
一对多关联会把头上的金额按明细复制,看起来像增长,其实是扇形。COUNT 和 COUNT DISTINCT 不是同一指标。NULL 不是 0。日期函数没有世界语,能写绝对区间就写绝对区间。
复杂逻辑用公共表表达式拆开。拆开是为了给人看中间结果。先对再快。用索引去救一条口径错误的语句,会把错误生产化。
读完这一辑可以做什么
把你最近一条问数语句拆成三段 WITH:过滤、聚合、排名。每一段单独跑。有一段解释不清,就回到提问,不要在语句里继续加花样。
窗口不减少行。用它过滤之前,先确认粒度还在。