如何用SQL计算三个表UNION后月度不同类别的总占比
原SQL问题定位
- 核心逻辑偏差:语句拆分三个单表分别计算占比后用UNION拼接,未完成三表数据的合并汇总,输出结果是单表维度的类别占比,不是三表合并后的全局总占比
- 分母计算错误:每个子查询的分母是对应单表的当月总人数,并非三表合并后的当月全量总人数,分子分母统计维度不匹配
- 语法不兼容:三个子查询返回的占比列分别命名为percent_1、percent_2、percent_3,UNION操作要求所有SELECT的列数、列类型完全一致,后续很容易出现结果错位
- UNION自带去重逻辑:当不同子查询返回的记录值完全相同时,会被自动合并剔除,进一步导致统计结果失真
正确实现逻辑
统计核心遵循"先合并、再分层聚合、最后算占比"的流程:
- 先将三个表的明细数据做合并,针对跨表重复的同人记录做去重,避免无效计数
- 分层做两次聚合:第一次按「月份+类别」维度统计去重后的对应人数,第二次按「月份」维度统计当月全量总人数
- 关联两个聚合结果,用类别人数除以当月总人数得到最终占比
WITH all_valid_detail AS ( -- 合并三表明细,跨表同月份同同人同class的记录只保留1条 SELECT DISTINCT person, class, month FROM person_1 UNION SELECT DISTINCT person, class, month FROM person_2 UNION SELECT DISTINCT person, class, month FROM person_3 ), class_level_stat AS ( -- 按月份+类别统计人数 SELECT month, class, COUNT(DISTINCT person) AS class_person_cnt FROM all_valid_detail GROUP BY month, class ), month_total_stat AS ( -- 按月份统计全月总人数作为占比分母 SELECT month, COUNT(DISTINCT person) AS total_person_cnt FROM all_valid_detail GROUP BY month ) SELECT cls.month, cls.class, cls.class_person_cnt, CONCAT(ROUND(100 * cls.class_person_cnt / mt.total_person_cnt, 0), '%') AS class_percent FROM class_level_stat cls INNER JOIN month_total_stat mt ON cls.month = mt.month ORDER BY cls.month, cls.class
示例结果验证
针对给出的1月数据,合并后总人数为12人,统计结果完全匹配预期:
- class=1:累计5人,占比42%
- class=2:累计2人,占比16%
- class=3:累计5人,占比42%
内容的提问来源于stack exchange,提问作者nectar
相关产品推荐
相关产品推荐

