如何使用PostgreSQL统计各部门员工数并展示总计结果
需求说明
要实现的报表效果:
- 按部门维度拆分,统计每个部门的在职员工数量
- 报表末尾追加合计行,展示全公司在职员工总人数
原有SQL的问题
你写的代码是两个完全独立的查询,没有做分组统计、在职状态筛选、合计行关联的逻辑,既没法输出你要的统计结果,还可能因为多语句执行的配置问题抛出错误。你原来写UNION取两个表部门的逻辑,本意应该是想拿全量不重复的部门列表,但没有和员工计数逻辑结合,完全没实现统计效果。
PostgreSQL 实现方法
用PostgreSQL原生支持的ROLLUP分组扩展就能一次性出结果,不用写多个查询拼接,逻辑简单性能也好。
先默认通用表结构逻辑如下,你可以根据自己实际的字段名替换:
departments是部门表,存全量部门信息,部门标识字段和员工表关联employees是员工表,通过部门字段关联部门表,有字段标记员工是否在职(比如is_active = true代表在职,或者离职时间为空代表在职)
参考SQL代码:
SELECT -- ROLLUP生成的合计行部门字段返回NULL,统一转成「合计」展示 COALESCE(d.department_name, '合计') AS 部门, COUNT(e.employee_id) AS 在职员工数量 FROM departments d -- 左连接员工表,保证没有在职员工的部门也能显示0人,不会漏部门 LEFT JOIN employees e ON d.department = e.department -- 在职筛选条件写在JOIN子句里,避免左连接失效 AND e.is_active = TRUE -- 如果你的在职判断是resign_time IS NULL,替换成对应条件即可 GROUP BY ROLLUP(d.department_name) -- 排序保证合计行在最末尾,普通部门按名称升序排 ORDER BY -- 合计行(部门为NULL)排最后 CASE WHEN d.department_name IS NULL THEN 1 ELSE 0 END, d.department_name;
补充说明
- 如果你不需要统计「0在职员工」的部门,可以把
LEFT JOIN改成INNER JOIN,甚至可以直接从员工表分组统计,不用关联部门表 - 不建议用单独查部门人数、再单独查总人数UNION ALL的写法,不仅性能差,排序、空部门处理都容易出问题
- 如果你的部门名称直接存在员工表的
department字段,没有单独的部门维度表,把SQL里的部门表替换成(SELECT DISTINCT department FROM employees) d这个子查询就行
内容的提问来源于stack exchange,提问作者florence eghwrudje
相关产品推荐
相关产品推荐

