当前位置: 首页 > news >正文

【自记】SQL 中 GROUPING 和 GROUPING SETS 语句的案例说明

        我们用一个生活中的例子来理解,比如你开了家小超市,想统计「销售额」,但需要从多个角度看(比如按 “日期 + 商品”、“仅日期”、“仅商品”、“整体总销售额”)。

假设你的销售数据长这样(简化版):

日期商品销售额
2023-10-01可乐100
2023-10-01薯片80
2023-10-02可乐120
2023-10-02薯片90

你想同时得到 4 种统计结果:

  1. 按「日期 + 商品」统计(最明细的维度);
  2. 仅按「日期」统计(每天总销售额);
  3. 仅按「商品」统计(每种商品总销售额);
  4. 不按任何维度(整体总销售额)。

不用 GROUPING SETS 的话,你需要写 4 个查询,再合并:

-- 1. 日期+商品
SELECT 日期, 商品, SUM(销售额) FROM 销售表 GROUP BY 日期, 商品
UNION ALL
-- 2. 仅日期
SELECT 日期, 'ALL' 商品, SUM(销售额) FROM 销售表 GROUP BY 日期
UNION ALL
-- 3. 仅商品
SELECT 'ALL' 日期, 商品, SUM(销售额) FROM 销售表 GROUP BY 商品
UNION ALL
-- 4. 整体汇总
SELECT 'ALL' 日期, 'ALL' 商品, SUM(销售额) FROM 销售表

用 GROUPING SETS 的话,1 条查询搞定:

SELECT -- 用GROUPING判断列是否参与分组,不参与就显示'ALL'IF(GROUPING(日期) = 0, 日期, 'ALL') AS 日期,IF(GROUPING(商品) = 0, 商品, 'ALL') AS 商品,SUM(销售额) AS 总销售额
FROM 销售表
-- 一次性指定所有要统计的维度组合
GROUP BY 日期, 商品
GROUPING SETS ((日期, 商品),  -- 对应需求1:日期+商品(日期),        -- 对应需求2:仅日期(商品),        -- 对应需求3:仅商品()             -- 对应需求4:不分组(整体汇总)
)

最终结果长这样:

日期商品总销售额
2023-10-01可乐100-- 日期 + 商品维度
2023-10-01薯片80-- 日期 + 商品维度
2023-10-02可乐120-- 日期 + 商品维度
2023-10-02薯片90-- 日期 + 商品维度
2023-10-01ALL180-- 仅日期维度(100+80)
2023-10-02ALL210-- 仅日期维度(120+90)
ALL可乐220-- 仅商品维度(100+120)
ALL薯片170-- 仅商品维度(80+90)
ALLALL390-- 整体汇总(180+210 或 220+170)

核心点总结:

  • GROUPING SETS(...):括号里写多个 “维度组合”,一次查询得到所有组合的统计结果(代替多次GROUP BY+UNION ALL)。
  • GROUPING(列名):判断这一列是否在当前行的 “维度组合” 中。如果在(参与了分组),返回 0,显示实际值;如果不在(是汇总行),返回 1,用 'ALL' 标记,方便区分。

————————————

        我们用一个更贴近实际业务的例子来说明:假设你有一张「订单表」,需要统计不同维度的销量,同时保留一个固定的分组字段(比如「月份」),并穿插普通查询字段和GROUPING处理的字段,看看它们的区别。

场景设定

订单表orders结构(简化):

月份(month)地区(region)产品(product)销量(sales)
2023-09华北手机100
2023-09华北电脑50
2023-09华南手机80
2023-10华北手机120
2023-10华南电脑60

需求

统计每个月的销量,同时按以下维度组合分析:

  1. 月份 + 地区 + 产品(最明细)
  2. 月份 + 地区(不区分产品)
  3. 月份 + 产品(不区分地区)
  4. 月份(不区分地区和产品)

要求结果中:

  • 保留「月份」作为固定显示的普通字段;
  • 「地区」和「产品」用GROUPING处理,不参与分组时显示'ALL'
  • 计算总销量。

SQL 查询(包含普通字段和 GROUPING 字段)

SELECT -- 普通字段:月份(始终在GROUP BY中,直接显示实际值)month,-- GROUPING处理的字段:地区(是否参与分组动态显示)IF(GROUPING(region) = 0, region, 'ALL') AS region,-- GROUPING处理的字段:产品(是否参与分组动态显示)IF(GROUPING(product) = 0, product, 'ALL') AS product,-- 聚合字段:总销量SUM(sales) AS total_sales
FROM orders
-- 固定按月份分组,同时用GROUPING SETS定义地区和产品的组合
GROUP BY month,
GROUPING SETS ((region, product),  -- 组合1:月份+地区+产品(region),           -- 组合2:月份+地区(无产品)(product),          -- 组合3:月份+产品(无地区)()                  -- 组合4:仅月份(无地区和产品)
)
ORDER BY month, region, product;

查询结果

monthregionproducttotal_sales
2023-09华北手机100-- 组合 1:月份 + 地区 + 产品
2023-09华北电脑50-- 组合 1:月份 + 地区 + 产品
2023-09华北ALL150-- 组合 2:月份 + 地区(汇总该地区所有产品)
2023-09华南手机80-- 组合 1:月份 + 地区 + 产品
2023-09华南ALL80-- 组合 2:月份 + 地区(汇总该地区所有产品)
2023-09ALL手机180-- 组合 3:月份 + 产品(汇总所有地区该产品)
2023-09ALL电脑50-- 组合 3:月份 + 产品(汇总所有地区该产品)
2023-09ALLALL230-- 组合 4:仅月份(汇总该月所有销量)
2023-10华北手机120-- 组合 1:月份 + 地区 + 产品
2023-10华北ALL120-- 组合 2:月份 + 地区(汇总该地区所有产品)
2023-10华南电脑60-- 组合 1:月份 + 地区 + 产品
2023-10华南ALL60-- 组合 2:月份 + 地区(汇总该地区所有产品)
2023-10ALL手机120-- 组合 3:月份 + 产品(汇总所有地区该产品)
2023-10ALL电脑60-- 组合 3:月份 + 产品(汇总所有地区该产品)
2023-10ALLALL180-- 组合 4:仅月份(汇总该月所有销量)

普通字段 vs GROUPING 处理的字段:核心区别

  1. 普通字段(如month

    • 必须出现在GROUP BY中(否则 SQL 会报错,因为非聚合字段必须参与分组)。
    • 其值是「固定分组维度」,在所有结果行中都显示实际值(如2023-092023-10),不会被替换为'ALL'
    • 作用:作为所有统计维度的 “基础锚点”(比如这里所有统计都基于 “月份” 展开)。
  2. GROUPING 处理的字段(如regionproduct

    • 不一定在所有分组组合中出现(由GROUPING SETS控制)。
    • 其值是「动态分组维度」:当参与当前分组时显示实际值(如华北手机),不参与时显示'ALL'(表示该维度被汇总)。
    • 作用:灵活切换不同维度的统计视角,同时用'ALL'清晰标记 “当前行是该维度的汇总结果”。

        简单说:普通字段是 “固定不变的分组锚点”,GROUPING 处理的字段是 “可开关的动态维度”,前者值固定,后者值随分组组合动态变化(实际值或汇总标记)。


文章转载自:

http://cNy1klXF.pLxhq.cn
http://ZkbjVD5r.pLxhq.cn
http://bhaoaYSG.pLxhq.cn
http://Sh6bABJY.pLxhq.cn
http://GVZo2UGA.pLxhq.cn
http://WDB7v1sZ.pLxhq.cn
http://IINYu8h8.pLxhq.cn
http://J7PECndO.pLxhq.cn
http://XNdhYklY.pLxhq.cn
http://RqKHb4me.pLxhq.cn
http://AiR7DMRi.pLxhq.cn
http://uZiQnxKd.pLxhq.cn
http://B2zKvSxF.pLxhq.cn
http://bLASHuAM.pLxhq.cn
http://Lr8PyWxc.pLxhq.cn
http://l29n0XsR.pLxhq.cn
http://1RYonILF.pLxhq.cn
http://rXda1Gox.pLxhq.cn
http://qTKtLcVc.pLxhq.cn
http://b8OiPWqu.pLxhq.cn
http://Bw8jyblP.pLxhq.cn
http://Seulm7nT.pLxhq.cn
http://ZsQ4GzE9.pLxhq.cn
http://euoQP34D.pLxhq.cn
http://SCiIELyd.pLxhq.cn
http://gxFDuabg.pLxhq.cn
http://h25lKvNT.pLxhq.cn
http://8E1h4Y32.pLxhq.cn
http://F2FjdFsu.pLxhq.cn
http://kBdxyGbJ.pLxhq.cn
http://www.dtcms.com/a/379300.html

相关文章:

  • Codeforces Round 1048 (Div. 2)
  • CFD专栏丨ultraFluidX 动力舱热仿真
  • QTday1作业
  • Linux基本指令(7)
  • 车载数据采集(DAQ)解析
  • 计算机组成原理:定点加法、减法运算
  • Cursor 不香了?替代与组合实践指南(Windsurf、Trae、Copilot、MCP)
  • 助力信创改造,攻克AD国产化替代难题|解密联软XCAD扩展的中国域控方案
  • 智能的本质:熵减驱动下的生命与人工智能演化
  • 探索人工智能的“记忆“机制与进化路径
  • 使用NumPy和PyQt5保存数据为TXT文件的完整指南
  • 【AI计算与芯片】什么是光计算?
  • 爱校对正式入驻抖音店铺,为更多用户带来专业文字校对服务
  • 项目1——单片机程序审查,控制系统流程图和时序图
  • 完美解决:应用版本更新,增加字段导致 Redis 旧数据反序列化报错
  • 探索数据库世界:从基础类型到实际应用
  • ui指针遇到问题
  • 安卓13_ROM修改定制化-----禁用 Android 导航按键的几种操作
  • VMWare使用文件夹共享操作步骤
  • 【Nginx开荒攻略】Nginx入门:核心概念与架构设计
  • MQTT协议回顾
  • 端到端语音交互数据 精准赋能语音大模型进阶
  • 大模型在题目生成中的安全研究:攻击方法与防御机制
  • 可达性分析: 什么东西可以被当作根
  • Spring框架中的常见面试题
  • JavaScript 中 map 和 filter 方法的快速上手指南 (附综合案例)
  • C#写字符串到Modbus中
  • 基于SpringBoot+Vue.js开发的个人健康管理系统
  • 文心一言-Agent岗三轮面试全记录
  • 机器人集群调度算法简介与实现思路