SQL分组查询的分层统计是指按照多个层级维度对数据进行分组汇总,既可以获取每个细分层级的统计数据,也能得到上级层级的合计结果,在业务报表、数据看板等场景中非常实用。常见的实现方式包括多字段GROUP BY分组和WITH ROLLUP扩展两种,下面结合实际案例详细说明。

一、基础准备:示例数据表
首先我们创建一个销售记录表sales_record,包含区域、城市、销售额三个字段,后续的操作都基于这张表展开。
-- 创建示例表
CREATE TABLE sales_record (
region VARCHAR(20) COMMENT '区域',
city VARCHAR(20) COMMENT '城市',
sales_amount DECIMAL(10,2) COMMENT '销售额'
);
-- 插入测试数据
INSERT INTO sales_record (region, city, sales_amount) VALUES
('华东', '上海', 15000.00),
('华东', '杭州', 12000.00),
('华东', '南京', 11000.00),
('华南', '广州', 13000.00),
('华南', '深圳', 14000.00),
('华北', '北京', 16000.00),
('华北', '天津', 10000.00);
二、多字段GROUP BY实现基础分层统计
如果需要同时按照区域和城市两个层级统计销售额,只需要在GROUP BY子句中同时指定两个字段即可,查询结果会先按第一个字段分组,再在组内按第二个字段分组。
-- 按区域、城市两个层级统计销售额
SELECT
region,
city,
SUM(sales_amount) AS total_sales
FROM sales_record
GROUP BY region, city
ORDER BY region, city;
上述查询的结果会先按区域分组,每个区域下再按城市分组,输出每个城市对应的销售额总和,结果如下:
| region | city | total_sales |
|---|---|---|
| 华东 | 上海 | 15000.00 |
| 华东 | 杭州 | 12000.00 |
| 华东 | 南京 | 11000.00 |
| 华南 | 广州 | 13000.00 |
| 华南 | 深圳 | 14000.00 |
| 华北 | 北京 | 16000.00 |
| 华北 | 天津 | 10000.00 |
三、WITH ROLLUP实现带合计的分层统计
如果除了需要每个层级的明细统计,还需要每个上级层级的合计以及所有数据的总计,可以使用GROUP BY的WITH ROLLUP扩展。WITH ROLLUP会在分组结果的基础上,自动生成每个分组的上级汇总行,汇总行的分组字段会显示为NULL。
-- 带合计的分层统计
SELECT
region,
city,
SUM(sales_amount) AS total_sales
FROM sales_record
GROUP BY region, city WITH ROLLUP
ORDER BY region, city;
上述查询的结果除了每个城市的销售额,还会生成每个区域的总销售额(对应city为NULL的行),以及所有区域的总销售额(对应region和city都为NULL的行),结果如下:
| region | city | total_sales |
|---|---|---|
| 华东 | 上海 | 15000.00 |
| 华东 | 杭州 | 12000.00 |
| 华东 | 南京 | 11000.00 |
| 华东 | NULL | 38000.00 |
| 华南 | 广州 | 13000.00 |
| 华南 | 深圳 | 14000.00 |
| 华南 | NULL | 27000.00 |
| 华北 | 北京 | 16000.00 |
| 华北 | 天津 | 10000.00 |
| 华北 | NULL | 26000.00 |
| NULL | NULL | 91000.00 |
四、注意事项
- 使用WITH ROLLUP时,ORDER BY子句不能对分组字段使用非分组表达式,否则会导致汇总行顺序异常,建议直接使用分组字段排序。
- 如果需要对汇总行的NULL值进行替换,可以使用
COALESCE()函数,比如COALESCE(region, '总计')可以把region为NULL的汇总行显示为总计。 - WITH ROLLUP的层级顺序和GROUP BY后面的字段顺序一致,第一个字段是最高层级,最后一个字段是最低层级,调整字段顺序会改变汇总的层级逻辑。
分层统计的核心是明确分组的层级顺序,多字段GROUP BY适合只需要明细层级的场景,WITH ROLLUP适合需要同时获取明细和合计的场景,开发者可以根据实际需求选择合适的方式。