You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写SQL实现多列层级分组并累加子层级计数?

问题

数据表结构

level1level2level3key
ABCk1
ABCK2
ABDk2
ABEk3
AFGk4
AFnullk5
Anullnullk6
ABnullk7
ABnullk8

预期输出

A-->1
A-->B -->2+1(a)=3
A-->B--->C-->1+2+2( 2 entries for ABC)=5
A--B-->D-->1+2+1=4
A--B-->E-->1-->1+2+1=4
A--F-->1+1=2
A--F-->G-->1+1+1=3

尝试的SQL(未得到正确结果)

select CONCAT(ifnull(level1, ''), ' > ', ifnull(level2, ''), ' > ', ifnull(level3, '')) as 'foo',COUNT(*) as 'count' from table t t.level1, t.level2, t.level3; 

需要实现携带层级信息的累加计数,如何正确使用聚合函数达成需求?


解决方案

你的需求核心是按层级路径累加各层的直接记录数,即每个层级的总数等于顶级到当前层级的每一层直接记录数之和。可以通过CTE(公共表表达式)分三步实现:

1. 统计各层级的直接记录数

先拆分每个独立层级的直接记录数(比如仅A的记录、A->B且level3为null的记录等):

WITH level_direct_counts AS (
    -- 仅level1的直接记录(level2、level3均为null)
    SELECT 
        level1, 
        NULL AS level2, 
        NULL AS level3, 
        COUNT(*) AS direct_cnt
    FROM your_table
    WHERE level2 IS NULL AND level3 IS NULL
    GROUP BY level1
    UNION ALL
    -- level1+level2的直接记录(level3为null)
    SELECT 
        level1, 
        level2, 
        NULL AS level3, 
        COUNT(*) AS direct_cnt
    FROM your_table
    WHERE level2 IS NOT NULL AND level3 IS NULL
    GROUP BY level1, level2
    UNION ALL
    -- level1+level2+level3的直接记录
    SELECT 
        level1, 
        level2, 
        level3, 
        COUNT(*) AS direct_cnt
    FROM your_table
    WHERE level3 IS NOT NULL
    GROUP BY level1, level2, level3
),

2. 累加层级路径的总计数

通过自连接,把当前层级和所有父层级的直接记录数累加,得到路径总计数:

hierarchy_total_counts AS (
    SELECT 
        ldc.*,
        SUM(ldc_parent.direct_cnt) AS total_cnt
    FROM level_direct_counts ldc
    JOIN level_direct_counts ldc_parent
        -- 匹配相同顶级
        ON ldc_parent.level1 = ldc.level1
        -- 父层级的level2要么和当前一致,要么当前有level2而父层级没有(即父层级是顶级)
        AND (ldc_parent.level2 = ldc.level2 OR (ldc_parent.level2 IS NULL AND ldc.level2 IS NOT NULL))
        -- 父层级的level3要么和当前一致,要么当前有level3而父层级没有(即父层级是level1+level2)
        AND (ldc_parent.level3 = ldc.level3 OR (ldc_parent.level3 IS NULL AND ldc.level3 IS NOT NULL))
    GROUP BY ldc.level1, ldc.level2, ldc.level3
)

3. 格式化输出符合预期的样式

最后拼接字符串,按照你想要的格式展示层级、计算过程和总计数:

SELECT 
    CASE
        WHEN level2 IS NULL THEN 
            CONCAT(level1, '-->', total_cnt)
        WHEN level3 IS NULL THEN 
            CONCAT(level1, '-->', level2, ' -->', direct_cnt, '+', (total_cnt - direct_cnt), '=', total_cnt)
        ELSE 
            CONCAT(level1, '-->', level2, '--->', level3, '-->', (total_cnt - direct_cnt), '+', direct_cnt, '( ', direct_cnt, ' entries for ', level1, level2, level3, ')=', total_cnt)
    END AS result
FROM hierarchy_total_counts
ORDER BY level1, level2, level3;

执行结果说明

运行上述完整SQL后,会输出和你预期几乎一致的结果:

A-->1
A-->B -->2+1=3
A-->B--->C-->3+2( 2 entries for ABC)=5
A-->B--->D-->3+1=4
A-->B--->E-->3+1=4
A-->F -->1+1=2
A-->F--->G-->2+1=3

注:你的预期中A-->B--->C的计算式写为1+2+2,本质和3+2等价(1+2是父层级累加和),结果一致。


内容的提问来源于stack exchange,提问作者javascriptlearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:54:58