如何编写SQL查询获取重复次数最少的office_id对应的员工姓名?
解决方案
首先纠正你当前代码的问题:你按first_name分组统计的是每个姓名对应的office_id出现次数,这和需求的“统计各办公室的员工数量,找到人数最少的办公室并获取其员工姓名”完全不符,需要调整思路。
方法一:使用子查询(最直观的实现)
这种方式逻辑清晰,适配大多数数据库:
SELECT first_name FROM employees WHERE office_id = ( -- 先找到员工数量最少的office_id SELECT office_id FROM employees GROUP BY office_id ORDER BY COUNT(*) ASC -- 按员工数升序排序 LIMIT 1 -- 取第一个即人数最少的办公室 );
逻辑说明:
- 内层子查询按
office_id分组,统计每个办公室的员工总数,按数量从小到大排序后取第一个,得到人数最少的办公室ID。 - 外层查询根据这个ID筛选出对应办公室的所有员工姓名。
方法二:无需嵌套子查询(使用窗口函数,适配MySQL 8+、PostgreSQL、SQL Server等)
如果你的数据库支持窗口函数,可以用更简洁的方式实现:
SELECT first_name FROM ( SELECT first_name, -- 按办公室员工数排名,人数最少的排第1 RANK() OVER (ORDER BY COUNT(*) OVER (PARTITION BY office_id) ASC) AS office_rank FROM employees ) ranked_employees WHERE office_rank = 1;
逻辑说明:
- 内层查询中,
COUNT(*) OVER (PARTITION BY office_id)计算每个员工所在办公室的总人数。 RANK()函数根据这个总人数给每个员工排名,人数最少的办公室的员工排名为1。- 外层筛选出排名为1的员工姓名即可。
注意事项
如果存在多个办公室员工数量相同且都是最少的情况:
- 方法一的
LIMIT 1只会返回其中一个办公室的员工,若要返回所有最少人数办公室的员工,需要调整子查询为WHERE COUNT(*) = (SELECT MIN(cnt) FROM (SELECT COUNT(*) AS cnt FROM employees GROUP BY office_id) t)。 - 方法二的
RANK()会自动保留所有排名为1的员工,无需额外修改。
内容的提问来源于stack exchange,提问作者MikeHD
相关产品推荐
相关产品推荐

