标准答案

  1. 需要每个租户、日期或类别只返回一行的计数、求和或最大值时,GROUP BY 更直接;如果还要保留每条明细,就使用窗口函数。
  2. 窗口的 PARTITION BY 决定分组范围,ORDER BY 决定计算顺序,ROWS/RANGE/GROUPS 等 frame 决定累计窗口,默认 frame 不能想当然。
  3. ROW_NUMBER、RANK 和 DENSE_RANK 对并列值的处理不同,Top N、取每组第一条和分页必须先定义并列规则。
  4. 大数据量窗口计算常需要排序和内存,可能产生临时文件;应结合 work_mem、分区大小、索引和实际计划评估。
  5. 窗口结果仍需稳定的 tie-breaker,例如时间相同再按唯一 ID 排序,否则翻页或重跑可能出现顺序变化。

题目解析

两者最核心的区别是结果形状:GROUP BY 会减少行数,窗口函数通常保留明细。先确定接口或报表需要“每组一行”还是“每行带组内结果”,再选语法。

很多排名错误不是函数写错,而是没有定义并列和 frame。例如累计金额的默认 frame、同一时间戳的顺序、每组取第一条都需要稳定规则。

性能上要关注排序和分区大小。窗口函数可以写得很清楚,但如果每次请求都对全历史数据排序,最终仍需要汇总表、索引、分区或异步计算。

常见误区

  • 误区:用 GROUP BY 代替所有窗口计算。改正:如果要保留明细行,GROUP BY 会改变结果形状,应使用窗口函数或分层查询。
  • 误区:忽略 ROWS/RANGE 和默认 frame。改正:累计、排名和并列场景要显式定义 frame 与排序规则。
  • 误区:用窗口函数后不再看排序成本。改正:检查计划、临时文件、work_mem 和分区规模,避免把全表排序放进高频接口。

作者信息