如何查询所有stud_group_id均学习的subject_id?
解决思路与SQL实现
这是典型的查找被所有分组覆盖的条目问题,下面给你几种实用的SQL解法,都能满足你的需求:
方法1:GROUP BY + HAVING(推荐,简洁高效)
核心思路是:统计每个科目被多少个不同的学习小组学习,再和总小组数对比——如果数量相等,说明这个科目被所有小组都学习了。
SELECT subject_id FROM your_table_name -- 替换成你的实际表名 GROUP BY subject_id HAVING COUNT(DISTINCT stud_group_id) = ( SELECT COUNT(DISTINCT stud_group_id) FROM your_table_name );
解释:
- 子查询
(SELECT COUNT(DISTINCT stud_group_id) FROM your_table_name)先算出总共有多少个独立的学习小组(在你的示例里是3个:1g、2g、3g)。 - 外层的
GROUP BY subject_id按科目分组,COUNT(DISTINCT stud_group_id)统计每个科目对应的不同小组数量。 HAVING子句筛选出小组数量等于总小组数的科目,也就是被所有小组学习的科目。
方法2:NOT EXISTS 反逻辑查询
用双重否定的思路:找不存在任何一个学习小组没有学习该科目的subject_id。
SELECT DISTINCT t1.subject_id FROM your_table_name t1 WHERE NOT EXISTS ( -- 检查是否存在某个小组,没有学习t1的subject_id SELECT 1 FROM your_table_name t2 WHERE NOT EXISTS ( -- 检查该小组是否有学习t1的subject_id的记录 SELECT 1 FROM your_table_name t3 WHERE t3.stud_group_id = t2.stud_group_id AND t3.subject_id = t1.subject_id ) );
解释:
- 外层的
NOT EXISTS确保:对于当前的subject_id,找不到任何一个小组是没有学习它的。 - 这种写法逻辑严谨,适合复杂的关联场景,不过性能上不如第一种方法直观。
方法3:笛卡尔积+LEFT JOIN(适合理解逻辑)
通过生成所有可能的小组-科目组合,再排除那些不存在的组合,剩下的就是被所有小组学习的科目。
SELECT DISTINCT subject_id FROM your_table_name WHERE subject_id NOT IN ( -- 找出存在小组未学习的科目 SELECT s.subject_id FROM (SELECT DISTINCT stud_group_id FROM your_table_name) g CROSS JOIN (SELECT DISTINCT subject_id FROM your_table_name) s LEFT JOIN your_table_name t ON g.stud_group_id = t.stud_group_id AND s.subject_id = t.subject_id WHERE t.stud_group_id IS NULL );
解释:
CROSS JOIN生成所有小组和科目的组合(比如你的示例里会生成3个小组×4个科目=12种组合)。LEFT JOIN后,t.stud_group_id IS NULL的行就是「小组没学该科目」的情况,这些对应的subject_id就是不符合要求的。- 最后用
NOT IN排除这些科目,得到目标结果。
内容的提问来源于stack exchange,提问作者Pavel Antspovich
相关产品推荐
相关产品推荐

