group by用于报表统计,压缩行数生成部门总人数、平均薪资等摘要;partition by保留原始行数,为明细数据附加分组计算值,如部门内排名或历史平均工资。

它并不更适合报表统计——恰恰相反,GROUP BY 才是报表统计的主力,PARTITION BY 通常用于增强明细数据,不是替代 GROUP BY 的方案。
报表统计该用 GROUP BY,不是 PARTITION BY
所谓“报表统计”,比如“每个部门总人数、平均薪资、最高工资”,本质是压缩原始行、输出摘要。这正是 GROUP BY 的设计目标:它把 dept_id = 'd001' 的 27 行员工记录,聚合成 1 行结果。
-
GROUP BY dept_id后,SELECT dept_id, COUNT(*), AVG(salary)合法且高效 - 若强行用
AVG(salary) OVER (PARTITION BY dept_id),结果仍是 27 行,每行都重复写着同一个平均值——这不是报表,是冗余附加 - 多数 BI 工具(如 Tableau、Power BI)对接
GROUP BY查询天然友好;对窗口函数结果需额外去重或聚合,徒增逻辑
PARTITION BY 真正适合的场景:带明细的分析增强
当你需要保留每一行原始记录,同时附带分组计算值时,PARTITION BY 才不可替代。典型例子:
- 销售订单表里加一列
rank_within_product:用ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY amount DESC) - 用户行为日志中加
session_seq:用ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_time) - 股票行情中加 “过去 5 日涨跌幅”:用
AVG(close) OVER (PARTITION BY symbol ORDER BY date ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)
这些操作不产出报表,而是为下游分析提供更丰富的上下文字段。
一款AI工具,主要用于产品经理技能,适用于 Claude Code、Codex、Cursor 和 Windsurf。涵盖 SaaS 指标诊断、PRD 评审、路线图规划、需求探索,以及面向产品经理的职业转型辅导等,适合需要提升相关任务效率的用户。
混用时的执行顺序陷阱
GROUP BY 和 PARTITION BY 可以共存,但必须清楚执行时机:
-
GROUP BY在WHERE之后、SELECT之前执行,它看到的是原始行 -
PARTITION BY所在的窗口函数,在SELECT列确定后才计算,它能看到GROUP BY聚合后的结果行 - 例如:
SELECT dept_id, AVG(salary), COUNT(*) OVER (PARTITION BY dept_id)是合法的——但COUNT(*) OVER此时统计的是每个部门聚合后那 1 行,结果全是 1,毫无意义
性能和可读性常被低估的细节
在大表上盲目套用 PARTITION BY 做“伪汇总”,会带来实际负担:
-
GROUP BY通常触发哈希分组,内存占用可控;而PARTITION BY需扫描并维护每个分区的状态,若分区键基数极低(如PARTITION BY gender),可能退化为全表遍历 + 大量排序 - SQL 可读性下降:看到
OVER (PARTITION BY ...)就默认要保留明细行;如果实际想要报表,却写了窗口函数,后续同事或自己半年后回看,第一反应是“这里是不是漏了 GROUP BY?” - 数据库优化器对
GROUP BY的路径选择更成熟;对复杂窗口函数(尤其含ROWS或RANGE)的下推能力因引擎而异,MySQL 8.0 和 PostgreSQL 表现差异明显
真正容易被忽略的点是:PARTITION BY 不是 GROUP BY 的“升级版”或“平替”,它是另一条技术路径——前者保形,后者塑形。选错,不是慢一点,而是结果错一层。










