Assuming I have the tables student
, club
, and student_club
:
student {
id
name
}
club {
id
name
}
stude
Since noone has added this (classic) version:
SELECT s.*
FROM student AS s
WHERE NOT EXISTS
( SELECT *
FROM club AS c
WHERE c.id IN (30, 50)
AND NOT EXISTS
( SELECT *
FROM student_club AS sc
WHERE sc.student_id = s.id
AND sc.club_id = c.id
)
)
or similar:
SELECT s.*
FROM student AS s
WHERE NOT EXISTS
( SELECT *
FROM
( SELECT 30 AS club_id
UNION ALL
SELECT 50
) AS c
WHERE NOT EXISTS
( SELECT *
FROM student_club AS sc
WHERE sc.student_id = s.id
AND sc.club_id = c.club_id
)
)
One more try with a slightly different approach. Inspired by an article in Explain Extended: Multiple attributes in a EAV table: GROUP BY vs. NOT EXISTS:
SELECT s.*
FROM student_club AS sc
JOIN student AS s
ON s.student_id = sc.student_id
WHERE sc.club_id = 50 --- one option here
AND NOT EXISTS
( SELECT *
FROM
( SELECT 30 AS club_id --- all the rest in here
--- as in previous query
) AS c
WHERE NOT EXISTS
( SELECT *
FROM student_club AS scc
WHERE scc.student_id = sc.id
AND scc.club_id = c.club_id
)
)
Another approach:
SELECT s.stud_id
FROM student s
EXCEPT
SELECT stud_id
FROM
( SELECT s.stud_id, c.club_id
FROM student s
CROSS JOIN (VALUES (30),(50)) c (club_id)
EXCEPT
SELECT stud_id, club_id
FROM student_club
WHERE club_id IN (30, 50) -- optional. Not needed but may affect performance
) x ;