You need to enable JavaScript to run this app.
导航
GROUPING 函数
最近更新时间:2025.12.03 14:16:32首次发布时间:2025.12.03 14:16:32
复制全文
我的收藏
有用
有用
无用
无用

本文将介绍 GROUPING 函数与 GROUPING SETS 修饰符的用法,并介绍 GROUPING SETSCUBE 修饰符、基础 GROUP BY 子句的核心区别与适用场景。

GROUPING

ROLLUPCUBEGROUP BY 的修饰符,均用于计算数据小计:

  • ROLLUP 接收列的有序列表(如 (day, month, year)),会在聚合的每个层级依次计算小计,最终返回总计结果;
  • CUBE 会针对指定列的所有可能组合计算小计。

GROUPING 函数用于区分 ROLLUPCUBE 返回结果中的两类行:一类是更高层级的聚合行(superaggregate,即小计行),另一类是未使用 ROLLUP/CUBE 修饰时,GROUP BY 本身应返回的普通分组行。
GROUPING 函数接收多个列作为参数,返回一个位掩码(bitmask)值,其返回值含义如下:

  • 1:表示该行是经 ROLLUPCUBE 修饰的 GROUP BY 返回的小计行;
  • 0:表示该行不是经 ROLLUPCUBE 修饰的 GROUP BY 返回的小计行(即普通分组行)。

GROUPING SETS

默认情况下,CUBE 修饰符会对传入的所有列计算其所有可能组合的小计;而 GROUPING SETS 支持直接指定需要计算的具体列组合,使用更灵活。ROLLUPCUBEGROUPING SETS 修饰符的典型应用场景是层次化数据分析。
本文示例基于一张数据表,该表记录了两个数据中心中安装的 Linux 发行版及其对应版本信息;按「发行版」「版本」「数据中心位置」维度拆分查看这些数据,能为业务分析提供有效参考价值。

示例数据

本文将使用以下数据表作为示例,示例命令如下:
创建表:

CREATE DATABASE bh_demo;

CREATE TABLE bh_demo.servers (
    datacenter VARCHAR(255),
    distro VARCHAR(255) NOT NULL,
    version VARCHAR(50) NOT NULL,
    quantity INT
)
ENGINE = CnchMergeTree()  
ORDER BY (datacenter, distro, version);

插入数据:

INSERT INTO bh_demo.servers(datacenter, distro, version, quantity)
VALUES ('Schenectady', 'Arch','2022.08.05',50),
       ('Westport', 'Arch','2022.08.05',40),
       ('Schenectady','Arch','2021.09.01',30),
       ('Westport', 'Arch','2021.09.01',20),
       ('Schenectady','Arch','2020.05.01',10),
       ('Westport', 'Arch','2020.05.01',5),
       ('Schenectady','RHEL','9',60),
       ('Westport','RHEL','9',70),
       ('Westport','RHEL','7',80),
       ('Schenectady','RHEL','7',80)

查询数据:

SELECT 
    *
FROM
    bh_demo.servers;

查询结果:

┌─datacenter──┬─distro─┬─version────┬─quantity─┐
│ Schenectady │ Arch   │ 2020.05.01 │       10 │
│ Schenectady │ Arch   │ 2021.09.01 │       30 │
│ Schenectady │ Arch   │ 2022.08.05 │       50 │
│ Schenectady │ RHEL   │ 7          │       80 │
│ Schenectady │ RHEL   │ 9          │       60 │
│ Westport    │ Arch   │ 2020.05.01 │        5 │
│ Westport    │ Arch   │ 2021.09.01 │       20 │
│ Westport    │ Arch   │ 2022.08.05 │       40 │
│ Westport    │ RHEL   │ 7          │       80 │
│ Westport    │ RHEL   │ 9          │       70 │
└─────────────┴────────┴────────────┴──────────┘

10 行数据。耗时: 0.359 秒。

简单查询

以下查询通过基础 GROUP BY 子句,按不同维度统计服务器数量,明确各维度下的数量分布:

  • 按「数据中心 + 发行版」组合维度统计
    统计每个数据中心(datacenter)中各 Linux 发行版(distro)对应的服务器总数量。
    执行查询:

    SELECT
        datacenter,
        distro, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        datacenter,
        distro;
    

    查询结果:

    ┌─datacenter──┬─distro─┬─qty─┐
    │ Schenectady │ RHEL   │ 140 │
    │ Westport    │ Arch   │  65 │
    │ Schenectady │ Arch   │  90 │
    │ Westport    │ RHEL   │ 150 │
    └─────────────┴────────┴─────┘
    
    返回 4 行。耗时:0.060 秒。
    
  • 按「数据中心」单一维度统计
    统计每个数据中心(datacenter)对应的所有服务器总数量(不区分发行版)。
    执行查询:

    SELECT
        datacenter, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        datacenter;
    

    查询结果:

    ┌─datacenter──┬─qty─┐
    │ Westport    │ 215 │
    │ Schenectady │ 230 │
    └─────────────┴─────┘
    
    返回 2 行。用时:0.051 秒。 
    
  • 按「发行版」单一维度统计
    统计各 Linux 发行版(distro)对应的服务器总数量(不区分数据中心)。
    执行查询:

    SELECT
        distro, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        distro;
    

    查询结果:

    ┌─distro─┬─qty─┐
    │ Arch   │ 155 │
    │ RHEL   │ 290 │
    └────────┴─────┘
    
    查询返回 2 行。用时:0.037 秒。 
    
  • 全量统计(无分组维度)
    统计所有服务器的总数量(不区分数据中心和发行版)。
    执行查询:

    SELECT
        SUM(quantity) qty
    FROM
        bh_demo.servers;
    

    查询结果:

    ┌─qty─┐
    │ 445 │
    └─────┘
    
    返回 1 行。耗时:0.030 秒。 
    

对比 GROUP BY 与 GROUPING SETS 的查询差异

以下示例对比了两种实现 “多维度聚合统计” 的方式:

  • 前者使用基础 GROUP BY 结合 UNION ALL 拼接子查询;
  • 后者使用 GROUPING SETS 单语句实现。

以下示例的核心目的均为一次性获取「数据中心 + 发行版」「数据中心」「发行版」及「全量」四个维度的服务器数量统计结果。

  • 使用 GROUP BY 查询
    执行查询:

    SELECT
        datacenter,
        distro, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        datacenter,
        distro
    UNION ALL
    SELECT
        datacenter, 
        null,
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        datacenter
    UNION ALL
    SELECT
        null,
        distro, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        distro
    UNION ALL
    SELECT
        null,
        null,
        SUM(quantity) qty
    FROM
        bh_demo.servers;
    

    查询结果:

    ┌─datacenter─┬─distro─┬─qty─┐
    │ ᴺᵁᴸᴸ       │ ᴺᵁᴸᴸ   │ 445 │
    └────────────┴────────┴─────┘
    ┌─datacenter──┬─distro─┬─qty─┐
    │ Westport    │ ᴺᵁᴸᴸ   │ 215 │
    │ Schenectady │ ᴺᵁᴸᴸ   │ 230 │
    └─────────────┴────────┴─────┘
    ┌─datacenter──┬─distro─┬─qty─┐
    │ Schenectady │ RHEL   │ 140 │
    │ Westport    │ Arch   │  65 │
    │ Schenectady │ Arch   │  90 │
    │ Westport    │ RHEL   │ 150 │
    └─────────────┴────────┴─────┘
    ┌─datacenter─┬─distro─┬─qty─┐
    │ ᴺᵁᴸᴸ       │ Arch   │ 155 │
    │ ᴺᵁᴸᴸ       │ RHEL   │ 290 │
    └────────────┴────────┴─────┘
    
    返回 9 行。耗时:0.066 秒。 
    
  • 使用 GROUPING SETS 查询
    执行查询:

    SELECT
        datacenter,
        distro, 
        SUM (quantity) qty
    FROM
        bh_demo.servers
    GROUP BY
        GROUPING SETS(
            (datacenter,distro),
            (datacenter),
            (distro),
            ()
        );
    

    查询结果:

    ┌─datacenter──┬─distro─┬─qty─┐
    │ Schenectady │ RHEL   │ 140 │
    │ Westport    │ Arch   │  65 │
    │ Schenectady │ Arch   │  90 │
    │ Westport    │ RHEL   │ 150 │
    └─────────────┴────────┴─────┘
    ┌─datacenter──┬─distro─┬─qty─┐
    │ Westport    │        │ 215 │
    │ Schenectady │        │ 230 │
    └─────────────┴────────┴─────┘
    ┌─datacenter─┬─distro─┬─qty─┐
    │            │        │ 445 │
    └────────────┴────────┴─────┘
    ┌─datacenter─┬─distro─┬─qty─┐
    │            │ Arch   │ 155 │
    │            │ RHEL   │ 290 │
    └────────────┴────────┴─────┘
    
    返回9行。耗时:0.040 秒。
    

对比 CUBE 与 GROUPING SETS 的查询差异

CUBE 会对指定列生成所有可能的组合维度(包含无效 / 无意义的组合),例如,以下 CUBE 查询中使用的 CUBE(datacenter, distro, version) 修饰符,生成的列组合层次结构可能不符合实际分析需求。因为跨不同发行版(Arch 和 RHEL)比较版本并无实际意义,二者的发布周期与版本命名规范存在差异,直接对比缺乏参考价值。
GROUPING SETS 支持自定义仅需统计的有效维度组合,更贴合业务需求,例如,以下示例中 GROUPING SETSdistro(发行版)与 version(版本)纳入同一分组集合,确保版本对比始终基于同一发行版维度,分析逻辑更合理。

  • 使用 CUBE 查询
    执行查询:

    SELECT
       datacenter,
       distro,
       version,
       SUM(quantity)
    FROM
       bh_demo.servers
    GROUP BY
       CUBE(datacenter,distro,version)
    ORDER BY
       datacenter,
       distro;
    

    查询结果:

    ┌─datacenter──┬─distro─┬─version────┬─sum(quantity)─┐
    │             │        │ 7          │           160 │
    │             │        │ 2020.05.01 │            15 │
    │             │        │ 2021.09.01 │            50 │
    │             │        │ 2022.08.05 │            90 │
    │             │        │ 9          │           130 │
    │             │        │            │           445 │
    │             │ Arch   │ 2021.09.01 │            50 │
    │             │ Arch   │ 2022.08.05 │            90 │
    │             │ Arch   │ 2020.05.01 │            15 │
    │             │ Arch   │            │           155 │
    │             │ RHEL   │ 9          │           130 │
    │             │ RHEL   │ 7          │           160 │
    │             │ RHEL   │            │           290 │
    │ Schenectady │        │ 9          │            60 │
    │ Schenectady │        │ 2021.09.01 │            30 │
    │ Schenectady │        │ 7          │            80 │
    │ Schenectady │        │ 2022.08.05 │            50 │
    │ Schenectady │        │ 2020.05.01 │            10 │
    │ Schenectady │        │            │           230 │
    │ Schenectady │ Arch   │ 2022.08.05 │            50 │
    │ Schenectady │ Arch   │ 2021.09.01 │            30 │
    │ Schenectady │ Arch   │ 2020.05.01 │            10 │
    │ Schenectady │ Arch   │            │            90 │
    │ Schenectady │ RHEL   │ 7          │            80 │
    │ Schenectady │ RHEL   │ 9          │            60 │
    │ Schenectady │ RHEL   │            │           140 │
    │ Westport    │        │ 9          │            70 │
    │ Westport    │        │ 2020.05.01 │             5 │
    │ Westport    │        │ 2022.08.05 │            40 │
    │ Westport    │        │ 7          │            80 │
    │ Westport    │        │ 2021.09.01 │            20 │
    │ Westport    │        │            │           215 │
    │ Westport    │ Arch   │ 2020.05.01 │             5 │
    │ Westport    │ Arch   │ 2021.09.01 │            20 │
    │ Westport    │ Arch   │ 2022.08.05 │            40 │
    │ Westport    │ Arch   │            │            65 │
    │ Westport    │ RHEL   │ 9          │            70 │
    │ Westport    │ RHEL   │ 7          │            80 │
    │ Westport    │ RHEL   │            │           150 │
    └─────────────┴────────┴────────────┴───────────────┘
    
    返回 39 行。耗时:0.051 秒。 
    

    注意

    若版本未与发行版建立关联维度,即上述示例中单独拆分的 version(发行版版本),则该分组逻辑缺乏实际分析意义;若需分析的是内核版本,则该组合逻辑更合理,原因是内核版本具备跨发行版的通用性,可与任一发行版关联。
    这种场景下,选择 GROUPING SETS 进行分组查询(如下一个示例所示),会更贴合实际分析需求。

  • 使用 GROUPING SETS 查询
    执行查询:

    SELECT
        datacenter,
        distro,
        version,
        SUM(quantity)
    FROM bh_demo.servers
    GROUP BY
        GROUPING SETS (
            (datacenter, distro, version),
            (datacenter, distro));
    

    查询结果:

    ┌─datacenter──┬─distro─┬─version────┬─sum(quantity)─┐
    │ Westport    │ RHEL   │ 9          │            70 │
    │ Schenectady │ Arch   │ 2022.08.05 │            50 │
    │ Schenectady │ Arch   │ 2021.09.01 │            30 │
    │ Schenectady │ RHEL   │ 7          │            80 │
    │ Westport    │ Arch   │ 2020.05.01 │             5 │
    │ Westport    │ RHEL   │ 7          │            80 │
    │ Westport    │ Arch   │ 2021.09.01 │            20 │
    │ Westport    │ Arch   │ 2022.08.05 │            40 │
    │ Schenectady │ RHEL   │ 9          │            60 │
    │ Schenectady │ Arch   │ 2020.05.01 │            10 │
    └─────────────┴────────┴────────────┴───────────────┘
    ┌─datacenter──┬─distro─┬─version─┬─sum(quantity)─┐
    │ Schenectady │ RHEL   │         │           140 │
    │ Westport    │ Arch   │         │            65 │
    │ Schenectady │ Arch   │         │            90 │
    │ Westport    │ RHEL   │         │           150 │
    └─────────────┴────────┴─────────┴───────────────┘
    
    返回 14 行。耗时: 0.041 秒