+------+--------+---------+
| id | teacher|student |
+-------+-------+---------+
| 1 | 1 |1 |
| 2 | 3 |3 |
| 3 | 3 |4 |
| 4 | 3 |5 |
| 5 | 3 |6 |
| 6 | 4 |5 |
| 7 | 4 |6 |
+-------+-------+---------+
Это как таблица связей "многие-ко-многим", как я могу запросить список студентов, где у них есть общий учитель, например, 3 и 4?
Я ожидаю, что смогу получить учеников 5 и 6, поскольку они оба "разделяют" одного и того же учителя?
что у меня сейчас есть
SELECT ts.studentId, ts.teacherId FROM teacher_students ts group by ts.studentId, ts.teacherId having ts.teacherId in (3,4);
Но я получаю ученика 3,4,5,6 вместо 5,6
использовать условный агрегат
select studentId from teacher_students t
where t.teacherId in (3,4)
group by t.studentId
having count(distinct t.teacherId )=2
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=70b3b2de9695f2f567afeaee7ec37bda
studentId
5
6
Вот один канонический способ сделать это:
SELECT studentId
FROM teacher_students
WHERE teacherId IN (3, 4)
GROUP BY studentId
HAVING MIN(teacherId) <> MAX(teacherId);
Одно из преимуществ вышеупомянутого запроса заключается в том, что он дружелюбен к индексу. В более общем плане, если вы хотите, чтобы учащиеся говорили с тремя или более общими учителями, вы можете использовать это:
SELECT studentId
FROM teacher_students
WHERE teacherId IN (...) -- some_num of teachers
GROUP BY studentId
HAVING COUNT(DISTINCT teacherId) = some_num;
teacherId in (1,2,3,4)
Вы можете также использовать where
положение с exists
:
SELECT ts.*
FROM teacher_students ts
WHERE teacherId IN (3,4) AND
EXISTS (SELECT 1
FROM teacher_students ts1
WHERE ts.studentId = ts1.studentId AND ts.teacherId <> ts1.teacherId
);