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()和窗口函数相结合,可以支持更多功能。