直接用 GROUP BY 配合 COUNT(*) 统计部门人数最常用高效,需确保 department 非 NULL、过滤软删除数据,避免用 COUNT(department) 或模糊匹配,零人数部门要用 LEFT JOIN 关联部门表并 COUNT(employees.id)。

直接用 GROUP BY 配合 COUNT(*) 就能完成,不需要子查询或窗口函数——除非你还要算占比、排名或跨层级统计。
基础写法:SELECT department, COUNT(*) + GROUP BY
这是最常用也最高效的统计方式。数据库引擎能直接利用索引(如果 department 列有索引)加速分组聚合。
- 确保
department字段不为NULL,否则NULL会被单独归为一组;如需排除,加WHERE department IS NOT NULL - 若员工表存在软删除字段(如
is_deleted = 0),务必在WHERE中过滤,否则统计会包含已离职人员 - 别用
COUNT(department)代替COUNT(*):前者会跳过该字段为NULL的行,而COUNT(*)统计所有行,语义更准确
遇到 department 是 JSON 或逗号分隔字符串怎么办?
这类设计本身就不适合直接聚合统计,强行查会导致性能差、结果错。必须先做数据规整。
- MySQL 8.0+ 可用
JSON_TABLE()拆解 JSON 数组;PostgreSQL 用jsonb_array_elements_text() - 逗号分隔(如
"HR,Finance")属于反范式设计,临时应急可用STRING_SPLIT()(SQL Server)或UNNEST(STRING_TO_ARRAY())(PostgreSQL),但长期应拆成关联表 - 千万别用
LIKE '%HR%'模糊匹配——会全表扫描,且无法区分 "HR" 和 "Engineering" 里的 "HR"
想同时显示零人数部门?用 LEFT JOIN 替代 INNER JOIN
如果部门信息存在独立的 departments 表,而员工表只存有效关联,那么单纯查员工表会漏掉无人部门。
- 正确做法:以
departments为主表,LEFT JOIN employees ON departments.id = employees.dept_id,再对employees.id计数(COUNT(employees.id)会把无匹配行记为 0) - 错误写法:
COUNT(*)在LEFT JOIN后仍会返回 1(因为部门行存在),导致零人数部门显示为 1 - 注意
COALESCE(COUNT(employees.id), 0)不必要——COUNT本身对空集就返回 0
真正容易被忽略的是数据一致性:部门名称大小写混用(如 "hr" / "HR")、前后空格、缩写不统一("Eng" vs "Engineering"),都会让同一部门被拆成多组。查之前先看 SELECT DISTINCT department FROM employees —— 如果结果比预期多,就得先清洗。

















