GROUP BY 和 PARTITION BY 的对比

John Doe 四月 8, 2023

摘要GROUP BYPARTITION BY子句在 SQL 中都用于对数据进行分组和计算聚合值,那么它们之间有什么区别呢?

scenery

目录

介绍

GROUP BYPARTITION BY 子句在 SQL 中用于对数据进行分组和计算聚合值。GROUP BY子句将结果集划分为多个组,每个组返回一行,而PARTITION BY子句将结果集划分为多个组,返回每个组中的每条记录,并带上每个组的聚合列。GROUP BY子句通常与SUM()AVG()等聚合函数一起使用,以计算每个组的总和或平均值。PARTITION BY子句不会减少返回的行数。PARTITION BY子句在选择分组列时提供了更大的灵活性,并允许在每个分组中使用不同的列。

GROUP BY 的使用

下面是一个例子用于展示如何将每个部门员工的平均薪水进行比较:

SELECT depname, avg(salary) FROM empsalary GROUP BY depname;
  depname  |          avg
-----------+-----------------------
 develop   | 5020.0000000000000000
 personnel | 3700.0000000000000000
 sales     | 4866.6666666666666667
(3 rows)

最开始的一个输出列直接来自于表empsalary,并且该列只能指定为进行分组的列。第二列表示根据depname值进行分组统计取得的平均薪水值。

PARTITION BY 的使用

下面是一个例子用于展示如何将每一个员工的薪水与他/她所在部门的平均薪水进行比较:

SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;
  depname  | empno | salary |          avg
-----------+-------+--------+-----------------------
 develop   |    11 |   5200 | 5020.0000000000000000
 develop   |     7 |   4200 | 5020.0000000000000000
 develop   |     9 |   4500 | 5020.0000000000000000
 develop   |     8 |   6000 | 5020.0000000000000000
 develop   |    10 |   5200 | 5020.0000000000000000
 personnel |     5 |   3500 | 3700.0000000000000000
 personnel |     2 |   3900 | 3700.0000000000000000
 sales     |     3 |   4800 | 4866.6666666666666667
 sales     |     1 |   5000 | 4866.6666666666666667
 sales     |     4 |   4800 | 4866.6666666666666667
(10 rows)

最开始的三个输出列直接来自于表empsalary,并且表中每一行都有一个输出行。第四列表示对与当前行具有相同depname值的所有表行取得平均值(这实际和非窗口avg聚集函数是相同的函数,但是OVER子句使得它被当做一个窗口函数处理并在一个合适的窗口帧上计算。)。

总结

虽然我们大多数时候使用GROUP BY,但在很多情况下,PARTITION BY会是更好的选择。在某些情况下,您可以使用子查询的GROUP BY来模拟PARTITION BY,但这些查询最终可能会非常复杂。

让我们用最重要的相似点和差异点来总结一切:

  • 相似点:两者都用于返回聚合值。
  • 差异点:使用GROUP BY子句隐藏了原始行,您无法在查询中访问原始行的记录值。另一方面,使用PARTITION BY子句可以保留原始列值,同时也允许我们生成聚合列值。
  • 差异点:PARTITION BYOVER()和窗口函数相结合,可以支持更多功能。