SQL中PARTITION BY和GROUP BY有什么区别_窗口函数原理解析
GROUP BY压缩行数生成聚合结果,PARTITION BY保留原始行数仅附加计算值;前者用于统计报表,后者用于明细分析并支持窗口函数排序、排名等操作。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
GROUP BY 会压缩行数,PARTITION BY 不改变行数
这可以说是两者最核心、最根本的区别。简单来说,GROUP BY 之后,你得到的结果集行数,会小于或等于原始数据中分组键的去重数量——数据被“压缩”了。而 PARTITION BY 则完全不同,它必须配合窗口函数(也就是 OVER())使用,其作用是在原有每一行数据上“附加”一个计算值,原始数据一条都不会少。
这里有个新手常踩的坑:有人会写 SELECT name, salary, A VG(salary) FROM emp GROUP BY name,本意是想查看每个人的工资以及他所在部门的平均工资。但实际上,这要么会报错,要么会产生逻辑错误。原因在于,A VG(salary) 是一个聚合值,name 是分组键,但查询中没有说明如何处理那些既非分组键、又非聚合函数的字段(比如这里的 salary 字段)。如果换成窗口函数的写法:A VG(salary) OVER (PARTITION BY dept_id),问题就迎刃而解了。这个写法不仅语法正确,还能在结果中保留每个人的 name、salary、dept_id 等全部明细信息。
- 记住一个铁律:
GROUP BY之后,SELECT列表里只能出现两种东西:分组字段本身,或者包裹了聚合函数(如 SUM、A VG、COUNT)的表达式。 PARTITION BY则出现在OVER()子句内部,它并不参与 SQL 标准执行顺序中的“分组”阶段。它的计算发生在SELECT产出结果之后,是一种“叠加”式的计算。- 从性能角度看:在大表上使用
GROUP BY,通常会触发哈希分组或排序操作,内存和磁盘的开销比较明显。而PARTITION BY在窗口计算阶段进行分区扫描,如果分区粒度很粗(比如整个表作为一个分区),那性能可能退化成全表遍历。
PARTITION BY 必须和 OVER() 一起用,不能单独存在
这一点必须明确:PARTITION BY 不是一个可以独立存在的 SQL 语句,它仅仅是 OVER() 子句的一个组成部分。如果你试图脱离 OVER() 单独使用它,比如写成 SELECT * FROM t PARTITION BY col,数据库会直接报错,告诉你语法非法。
来看一个典型的使用场景:如果你想为每个部门内的员工,按照薪资从高到低进行编号,同时还要保留所有原始字段,该怎么做?
SELECT emp_id, name, dept_id, salary,
ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rn
FROM employees;
在这段代码里,PARTITION BY dept_id 定义了“在每个部门内部进行独立编号”这个范围,ORDER BY salary DESC 指定了编号的顺序规则,而 ROW_NUMBER() 则是执行编号操作的窗口函数本身。
- 漏写
OVER()是初学者最高频的语法错误之一,常见的报错信息是 “missing window specification” 或类似提示。 PARTITION BY子句可以为空(即不写),此时整个结果集会被视为一个大的分区。例如,COUNT(*) OVER()会计算整个查询结果的总行数。- 多个
PARTITION BY字段用逗号分隔,其语义等同于多维分组。比如PARTITION BY region, year表示先按地区分区,再在每个地区内按年份分区。
GROUP BY 的执行时机早于 PARTITION BY
理解 SQL 的执行顺序至关重要。在标准的 SQL 执行流程中,GROUP BY 发生在 HA VING 子句之前,但在 SELECT 列表确定之后。而包含 PARTITION BY 的窗口函数,其计算时机要晚得多——它是在最终的 SELECT 列确定之后才进行的。这意味着,窗口函数“看到”的数据,是已经经过 WHERE 过滤、GROUP BY 聚合(如果用了的话)之后的数据。
由此引出一个关键结论:你无法在同一个查询中,既用 GROUP BY 把数据压缩成汇总行,又指望 PARTITION BY 能对原始的、未聚合的明细行进行分区计算。这两者是互斥的。
- 如果想同时得到部门汇总数据和员工明细数据怎么办?通常需要两个查询通过
UNION ALL组合,或者使用公共表表达式(CTE)分开处理。 - 在已经使用了
GROUP BY的查询里嵌套窗口函数时,PARTITION BY所分区的对象是聚合后的行,而非原始明细行。例如,SELECT dept_id, COUNT(*) cnt, SUM(cnt) OVER (PARTITION BY dept_id)这个查询中,每个部门的cnt已经是一个单独的聚合值,再对它按部门分区求和已经没有实际意义。 - 数据库兼容性需要注意:Oracle 和 PostgreSQL 等数据库支持在
GROUP BY之后使用窗口函数,但 MySQL 直到 8.0 版本才完全支持这种组合。在旧版 MySQL(如 5.7)中尝试这么做会直接报错。
别把 PARTITION BY 当成 GROUP BY 的替代品
有些人看到 PARTITION BY 也能“按某列分开计算”,就试图用它来绕过 GROUP BY 对 SELECT 列表的严格限制。比如,用 SELECT name, salary, A VG(salary) OVER (PARTITION BY dept_id) 来代替 GROUP BY dept_id。语法上这确实能执行,但两者的语义天差地别:前者返回所有员工的记录,并在每个人旁边附加其所在部门的平均工资;后者只返回每个部门一行数据,包含部门ID和该部门的平均工资。
选择依据其实很简单:问问自己,最终想要的是「汇总报告」还是「带有标记的明细」?
- 如果你的目标是生成统计报表、进行数据聚合后导出 → 毫不犹豫地选择
GROUP BY。 - 如果你的需求是做排名、计算累计求和、进行前后行比较,或者在保留所有明细的同时增加统计列 → 那么
PARTITION BY配合窗口函数就是你的最佳工具。 - 当需要混合使用时,务必先确认数据库版本是否支持,尤其要警惕 MySQL 5.7 及更早版本完全不支持窗口函数。
最后,还有一个真正容易被忽略的细节,它源于执行顺序带来的隐性依赖:当你的查询变得复杂,同时包含了 WHERE 过滤、GROUP BY 聚合和窗口函数时,PARTITION BY 所“看到”的数据,已经是经过层层过滤和聚合之后的结果了——它不会,也不可能回溯到最原始的表数据。这一点在编写复杂分析查询时,必须时刻牢记。
相关攻略
GROUP BY压缩行数生成聚合结果,PARTITION BY保留原始行数仅附加计算值;前者用于统计报表,后者用于明细分析并支持窗口函数排序、排名等操作。 GROUP BY 会压缩行数,PARTITION BY 不改变行数 这可以说是两者最核心、最根本的区别。简单来说,GROUP BY 之后,你得到
分区表设置只读:你以为的“安全锁”,可能只是“防君子不防小人” 在数据治理里,给历史分区加上“只读”标签,听起来是个一劳永逸的保护措施。但实际操作过的人都知道,这里面的水,比想象中要深。今天,我们就来拆解几个关键细节,看看这个“只读”开关,到底能管住什么,又管不住什么。 ALTER TABLE MO
2025年3月24日,据币安官方公告显示,币安 HODLer 空投现已上线第 13 期项目 Particle Network(PARTI), 币安将于 3 月 25 日 21:00(东八区时间)上线 PARTI,并开放 PARTI USDT、PARTI USDC、PARTI BNB、PARTI FDUSD 和 PARTI TRY 交易对,下文将为大家详细介绍
2025年3月24日,据币安官方公告显示,币安HODLer空投现已上线第13期项目Particle Network(PARTI),下文将为大家详细介绍
热门专题
热门推荐
Titan Books正式公开《刺客信条:黑旗 记忆重置》官方艺术设定集 对于《刺客信条》系列的粉丝,尤其是那些对爱德华·肯威的海盗传奇念念不忘的玩家来说,最近有个值得关注的消息。育碧的长期合作伙伴Titan Books,正式揭晓了《刺客信条:黑旗 记忆重置》(Assassin s Creed: B
欧易OKX安卓版官方下载与安装全攻略 想在手机上安全、便捷地交易加密货币?欧易OKX交易平台的安卓版应用是个不错的选择。作为一款领先的数字资产交易工具,它为用户提供了全面的服务。下面这份详细的指南,将手把手带你完成从下载、安装到注册认证的全过程,帮你轻松上手。 一、欧易OKX应用下载指南 第一步,也
名越工作室YouTube频道“消失”又“复活”,新作《Gang of Dragon》前景仍不明朗 最近游戏圈里有个消息,让不少玩家心里咯噔了一下。彭博社此前报道,网易可能将停止资助由知名制作人名越稔洋(《如龙》《审判》系列之父)领衔的“名越工作室”。这一下,让团队正在开发的首款游戏《Gang of
各位玩家朋友们早上好! 今天是2026年4月25日星期六,欢迎收看今天的晨播报。今天的主要内容有:尼古拉斯·凯奇主演的《暗影蜘蛛侠》发布了全新海报,备受喜爱的猫猫冒险游戏《流浪》确认将登陆Switch2平台,而《最终幻想14》也正式公布了其下一个大型资料片。话不多说,一起来看看具体详情。 1、《蜘蛛
《星球大战:银河赛车手》发售日疑似泄露,豪华版内容抢先看 备受期待的《星球大战》系列赛车游戏新作,最近似乎不小心“说漏了嘴”。根据其Steam商店页面上一张预购奖励图的显示,《星球大战:银河赛车手》(Star Wars: Galactic Racer)的正式发售日期,很可能定在了2026年10月6日





