MySQL按公司编码分组统计多表各层级人员去重计数方法
实现方案
核心避坑点:不要将五张表直接全量关联后计数。各人员表是自上而下的一对多层级关系,全量JOIN会产生笛卡尔积导致行数膨胀,要么计数错误,要么查询性能极差。
正确逻辑是先对每张人员表单独按公司维度预聚合,统计对应类型人员的去重数量,再和公司主表关联取CEO信息,最终输出结果。
可直接运行的SQL代码
SELECT c.company_code, c.ceo, COALESCE(l.lead_cnt, 0) AS lead_total, COALESCE(s.senior_cnt, 0) AS senior_total, COALESCE(m.manager_cnt, 0) AS manager_total, COALESCE(e.employee_cnt, 0) AS employee_total FROM Company c LEFT JOIN ( SELECT company_code, COUNT(DISTINCT lead_code) AS lead_cnt FROM Lead GROUP BY company_code ) l ON c.company_code = l.company_code LEFT JOIN ( SELECT company_code, COUNT(DISTINCT senior_code) AS senior_cnt FROM Senior GROUP BY company_code ) s ON c.company_code = s.company_code LEFT JOIN ( SELECT company_code, COUNT(DISTINCT manager_code) AS manager_cnt FROM Manager GROUP BY company_code ) m ON c.company_code = m.company_code LEFT JOIN ( SELECT company_code, COUNT(DISTINCT employee_code) AS employee_cnt FROM Employee GROUP BY company_code ) e ON c.company_code = e.company_code ORDER BY c.company_code;
结果验证
执行上述SQL后将输出和预期完全一致的统计结果:
| company_code | ceo | lead_total | senior_total | manager_total | employee_total |
|---|---|---|---|---|---|
| C1 | John | 1 | 2 | 1 | 2 |
| C2 | Andrew | 1 | 1 | 2 | 2 |
避坑说明
以下是两类高频错误写法,不建议使用:
- 全量JOIN五张表后再做
COUNT(DISTINCT)去重:小数据量下可能返回正确结果,但中间会生成数倍于原数据量的笛卡尔积,大表场景下极易引发数据库性能故障。 - 表关联后直接
COUNT()不做预聚合:会因为一对多关联的行复制问题,统计出的人员数远大于实际值。
内容的提问来源于stack exchange,提问作者Rishav44
相关产品推荐
相关产品推荐

