对于糟糕的标题抱歉,我想不出更好的方式来描述我的问题,所以我通过举例解释它来弥补它。
如果你想跟随,那么这是为我的问题创建表格的SQL:
CREATE TABLE `student_sections` (`student_id` int(11) NOT NULL, `section_id` int(11) NOT NULL);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (1,11);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (1,12);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (1,13);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (1,14);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (1,15);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,12);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,13);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,14);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,21);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,22);
INSERT INTO `student_sections` (`student_id`,`section_id`) VALUES (2,23);
这导致下表:
| student_sections |
|-------------------------|
| student_id | section_id |
|------------|------------|
| 1 | 11 |
| 1 | 12 |
| 1 | 13 |
| 1 | 14 |
| 1 | 15 |
| 2 | 12 |
| 2 | 13 |
| 2 | 14 |
| 2 | 21 |
| 2 | 22 |
| 2 | 23 |
我有一个“小组”的部分,我必须找到所有与部分组合相关的学生。我的应用程序将有几个章节组。
section_id的“第1组”:(11,12,13,14,15) 学生1与所有部分(11,12,13,14,15)相关联。 学生2与(12,13,14)相关但不与(11,15)相关联。
section_id的“第2组”:(21,22,23,24,25) 学生2与(21,22,23)有关,但与(24,25)无关。
给定section_id(12,13,14)我需要选择与section_id相关联的student_id,而不是section_id的(11,15)。
例如,如果给定section_id(12,13,14),我想选择student_id(2)。即使student_id 1与section_id(12,13,14)相关联,她也与11和15相关联,所以我不希望她的id返回。
此查询的更高目的是我将其用作子查询来选择给定组合部分的学生列表。
另外,例如,如果给定section_id(12,13),则不会返回任何结果。
我尝试使用IN和NOT IN的混合,但因为5行有student_id 1和3行与(12,13,14)相关联,以下查询中的DISTINT()返回student_id 1和2。
SELECT
DISTINCT(student_id)
FROM
student_sections
WHERE
section_id IN (12,13,14)
AND section_id NOT IN (11,15)
我添加了一些额外的用例数据,略微改变了查询的要求。学生将被安排在几个部门的“小组”中。
答案 0 :(得分:3)
对于此类查询,我建议使用having
子句进行聚合:
select ss.student_id
from student_sections ss
group by ss.student_id
having max(case when section_id = 12 then 1 else 0 end) = 1 and
max(case when section_id = 13 then 1 else 0 end) = 1 and
max(case when section_id = 14 then 1 else 0 end) = 1 and
max(case when section_id not in (12, 13, 14) then 1 else 0 end) = 0
这是同一个想法的一个更简单的版本:
select ss.student_id
from student_sections ss
group by ss.student_id
having count(distinct section_id) = 3 and
count(distinct case when section_id in (12, 13, 14) then section_id end) = 3
我喜欢第一个版本,因为它概括了很多“群内群体”问题。
答案 1 :(得分:1)
您需要选择两个选项:
SELECT student_id FROM student_sections
WHERE section_id IN (12,13,14)
INTERSECT
SELECT student_id WHERE
section_id NOT IN (11,15)
答案 2 :(得分:0)
SELECT student_id
, COUNT(*) x
, COUNT(CASE WHEN section_id IN(12,13,14) THEN 'foo' END) y
FROM student_sections
GROUP
BY student_id;
答案 3 :(得分:0)
这是另一种选择,但我喜欢@ Gordon的回答:
SELECT ss.student_id
FROM student_sections ss
left join (select student_id
from student_sections
where section_id NOT IN (12,13,14)
) s on ss.student_id = s.student_id
WHERE s.student_id is null
GROUP BY ss.student_id
HAVING Count(distinct ss.section_id) = 3
或使用NOT EXISTS:
SELECT ss.student_id
FROM student_sections ss
WHERE NOT EXISTS (
select null
from student_sections
where section_id NOT IN (12,13,14)
and student_id = ss.student_id
)
GROUP BY ss.student_id
HAVING Count(distinct ss.section_id) = 3
祝你好运。