ROLLUP 与 CUBE

PostgreSQL 汇总统计与窗口函数

Michel Semaan

Data Scientist

分组级合计

2008 年夏季奥运会中国与俄罗斯各奖牌类别的奖项数

| Country | Medal  | Awards |
|---------|--------|--------|
| CHN     | Bronze | 57     |
| CHN     | Gold   | 74     |
| CHN     | Silver | 53     |
| CHN     | Total  | 184    |
| RUS     | Bronze | 56     |
| RUS     | Gold   | 43     |
| RUS     | Silver | 44     |
| RUS     | Total  | 143    |
PostgreSQL 汇总统计与窗口函数

传统做法

SELECT
  Country, Medal, COUNT(*) AS Awards
FROM Summer_Medals
WHERE
  Year = 2008 AND Country IN ('CHN', 'RUS')
GROUP BY Country, Medal
ORDER BY Country ASC, Medal ASC

UNION ALL SELECT Country, 'Total', COUNT(*) AS Awards FROM Summer_Medals WHERE Year = 2008 AND Country IN ('CHN', 'RUS') GROUP BY Country, 2 ORDER BY Country ASC;
PostgreSQL 汇总统计与窗口函数

走近 ROLLUP

SELECT
  Country, Medal, COUNT(*) AS Awards
FROM Summer_Medals
WHERE
  Year = 2008 AND Country IN ('CHN', 'RUS')
GROUP BY Country, ROLLUP(Medal)
ORDER BY Country ASC, Medal ASC;
  • ROLLUPGROUP BY 的子句,会为分组级汇总添加额外行
  • GROUP BY Country, ROLLUP(Medal) 将先统计每个 CountryMedal 的合计,再仅统计 Country 的合计,并在这些行把 Medal 填为 null
PostgreSQL 汇总统计与窗口函数

ROLLUP - 查询

SELECT
  Country, Medal, COUNT(*) AS Awards
FROM summer_medals
WHERE
  Year = 2008 AND Country IN ('CHN', 'RUS')
GROUP BY ROLLUP(Country, Medal)
ORDER BY Country ASC, Medal ASC;
  • ROLLUP 具层级性,从最左列逐级向右去聚合
    • ROLLUP(Country, Medal) 包含 Country 级合计
    • ROLLUP(Medal, Country) 包含 Medal 级合计
    • 二者都包含总计
PostgreSQL 汇总统计与窗口函数

ROLLUP - 结果

| Country | Medal  | Awards |
|---------|--------|--------|
| CHN     | Bronze | 57     |
| CHN     | Gold   | 74     |
| CHN     | Silver | 53     |
| CHN     | null   | 184    |
| RUS     | Bronze | 56     |
| RUS     | Gold   | 43     |
| RUS     | Silver | 44     |
| RUS     | null   | 143    |
| null    | null   | 327    |
  • 分组级合计处为 null;全为 null 的行为总计
  • 注意未包含 Medal 级合计,因为用的是 ROLLUP(Country, Medal) 而非 ROLLUP(Medal, Country)
PostgreSQL 汇总统计与窗口函数

走近 CUBE

SELECT
  Country, Medal, COUNT(*) AS Awards
FROM summer_medals
WHERE
  Year = 2008 AND Country IN ('CHN', 'RUS')
GROUP BY CUBE(Country, Medal)
ORDER BY Country ASC, Medal ASC;
  • CUBE 是非层级的 ROLLUP
  • 它会生成所有可能的分组汇总
    • CUBE(Country, Medal) 统计 Country 级、Medal 级及总计
PostgreSQL 汇总统计与窗口函数

CUBE - 结果

| Country | Medal  | Awards |
|---------|--------|--------|
| CHN     | Bronze | 57     |
| CHN     | Gold   | 74     |
| CHN     | Silver | 53     |
| CHN     | null   | 184    |
| RUS     | Bronze | 56     |
| RUS     | Gold   | 43     |
| RUS     | Silver | 44     |
| RUS     | null   | 143    |
| null    | Bronze | 113    |
| null    | Gold   | 117    |
| null    | Silver | 97     |
| null    | null   | 327    |
  • 注意包含了 Medal 级别的合计
PostgreSQL 汇总统计与窗口函数

ROLLUP vs CUBE

Source

| Year | Quarter | Sales |
|------|---------|-------|
| 2008 | Q1      | 12    |
| 2008 | Q2      | 15    |
| 2009 | Q1      | 21    |
| 2009 | Q2      | 27    |
  • 数据有层级(如日期部件)且不需所有组合时用 ROLLUP
  • 需要所有可能的分组汇总时用 CUBE

ROLLUP(Year, Quarter)

| Year | Quarter | Sales |
|------|---------|-------|
| 2008 | null    | 27    |
| 2009 | null    | 48    |
| null | null    | 75    |

CUBE(Year, Quarter)

在上述行的基础上再加:

| Year | Quarter | Sales |
|------|---------|-------|
| null | Q1      | 33    |
| null | Q2      | 42    |
PostgreSQL 汇总统计与窗口函数

Let's practice!

PostgreSQL 汇总统计与窗口函数

Preparing Video For Download...