要用partition by还是group by,关键看是否保留原始行数:需明细用前者,要汇总用后者;两者语法位置、执行时机、输出结构均不同,混用会导致报错或逻辑错误。

要用 PARTITION BY 还是 GROUP BY,关键就看你要不要保留原始行数——要明细就选前者,要汇总就选后者。两者语法位置、执行时机、输出结构完全不同,混用不是报错就是逻辑错。
GROUP BY 报错“invalid use of group function”或字段不在 SELECT 列表中?
这是最典型的误用:在 SELECT 里同时写了未聚合的字段(如 name)和聚合函数(如 AVG(salary)),却没把 name 放进 GROUP BY。
-
GROUP BY要求:所有非聚合字段必须显式出现在GROUP BY子句中 - 聚合后每组只出一行,数据库不可能凭空决定该显示哪条
name - 合法写法只有两种:
SELECT dept_id, AVG(salary) FROM emp GROUP BY dept_id,或去掉AVG()改用窗口函数
PARTITION BY 单独写 SELECT * FROM t PARTITION BY col 就报错?
PARTITION BY 不是独立语法,它只是 OVER() 的一个参数。脱离 OVER() 使用会直接触发 “missing window specification” 类错误。
- 正确结构只有一种:
ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) -
PARTITION BY可以省略(即空着),此时整个结果集视为一个分区,例如COUNT(*) OVER()算总行数 - 多字段分区写成
PARTITION BY region, year,语义等同于先按region再按year嵌套分组
想给每行加个“部门平均工资”或“用户第几次访问”,为什么不能用 GROUP BY?
因为 GROUP BY 会压缩行数,而你需要的是在保留所有人/所有订单的前提下,附加一个计算值。
-
GROUP BY执行早于SELECT,它看到的是原始行;窗口函数在SELECT输出后才计算,能看到已处理过的字段 - 正确写法是:
AVG(salary) OVER (PARTITION BY dept_id)或ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_time) - 性能上:
GROUP BY常触发哈希分组或排序,内存压力大;PARTITION BY是分区扫描,但若分区键基数太低(比如用gender分区),可能退化为全表遍历
PARTITION BY 和表级 PARTITION(如 MySQL 的 PARTITION BY RANGE)是一回事吗?
不是。名字一样,但完全无关。
- 窗口函数里的
PARTITION BY是逻辑分组,纯 SQL 层行为,不依赖物理存储 - 建表时的
PARTITION BY RANGE或PARTITION BY HASH是存储层切分,影响数据落盘方式和查询下推能力 - 别被同名误导——一个跑在查询执行期,一个定义在表结构里











