Assuming I have the tables student
, club
, and student_club
:
student {
id
name
}
club {
id
name
}
student_club {
student_id
club_id
}
I want to know how to find all students in both the soccer (30) and baseball (50) club.
While this query doesn't work, it's the closest thing I have so far:
SELECT student.*
FROM student
INNER JOIN student_club sc ON student.id = sc.student_id
LEFT JOIN club c ON c.id = sc.club_id
WHERE c.id = 30 AND c.id = 50
So there's more than one way to skin a cat.
I'll to add two more to make it, well, more complete.
1) GROUP first, JOIN later
Assuming a sane data model where
(student_id, club_id)
is unique instudent_club
. Martin Smith's second version is like somewhat similar, but he joins first, groups later. This should be faster:2) EXISTS
And of course, there is the classic
EXISTS
. Similar to Derek's variant withIN
. Simple and fast. (In MySQL, this should be quite a bit faster than the variant withIN
):Since noone has added this (classic) version:
or similar:
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:
Another approach:
@erwin-brandstetter Please, benchmark this:
It's like number 6) by @sean , just cleaner, I guess.
Another CTE. It looks clean, but it will probably generate the same plan as a groupby in a normal subquery.
For those who want to test, a copy of my generate testdata thingy:
If you just want student_id then:
If you also need name from student then:
If you have more than two clubs in a club_selection table then:
Use of fastest variant (Mr. Sean in Mr. Brandstetter chart). May be variant with only one join to only the student_club matrix has the right to live. So, the longest query will have only two columns to calculate, idea is to make the query thin.