MySQL多对多关系查询:如何获取参与全部旅行的员工?
嘿,这个问题是SQL里挺经典的「全域匹配」场景,我来给你分享几种实际项目里常用的解法,每种都给你讲清思路和代码:
方法1:通过计数匹配总旅行数
思路很直接:先算出系统里总共有多少个旅行,再统计每个员工参与的旅行数量,只要这个数量等于总旅行数,就说明该员工参加了所有旅行。
如果employee_tour里没有重复报名的记录(同一个员工不会多次报同一个旅行),可以用这个SQL:
SELECT e.employee_id, e.employee_name FROM employee e JOIN employee_tour et ON e.employee_id = et.employee_id GROUP BY e.employee_id, e.employee_name HAVING COUNT(et.tour_id) = (SELECT COUNT(*) FROM tour);
要是employee_tour可能存在重复记录(比如员工误操作重复报名),那得用COUNT(DISTINCT)去重,避免统计数虚高:
SELECT e.employee_id, e.employee_name FROM employee e JOIN employee_tour et ON e.employee_id = et.employee_id GROUP BY e.employee_id, e.employee_name HAVING COUNT(DISTINCT et.tour_id) = (SELECT COUNT(*) FROM tour);
方法2:用NOT EXISTS做反证法
换个角度想:不存在任何一个旅行是该员工没参加的,那这个员工就符合要求。这种反证法的思路在大数据量场景下往往更高效,因为NOT EXISTS会用到短路判断,不用全量统计。
对应的SQL是:
SELECT e.employee_id, e.employee_name FROM employee e WHERE NOT EXISTS ( -- 找这个员工没参加的旅行 SELECT 1 FROM tour t WHERE NOT EXISTS ( SELECT 1 FROM employee_tour et WHERE et.employee_id = e.employee_id AND et.tour_id = t.tour_id ) );
小提醒
- 如果
tour表可能存在无效旅行(比如已取消的),记得在子查询里加过滤条件,比如SELECT COUNT(*) FROM tour WHERE is_active = 1 - 两种方法都要确保
employee_tour里的tour_id和employee_id都是有效的外键,避免脏数据影响结果
内容的提问来源于stack exchange,提问作者jonny thach
相关产品推荐
相关产品推荐

