Assuming I have the tables student
, club
, and student_club
:
student {
id
name
}
club {
id
name
}
stude
Another CTE. It looks clean, but it will probably generate the same plan as a groupby in a normal subquery.
WITH two AS (
SELECT student_id FROM tmp.student_club
WHERE club_id IN (30,50)
GROUP BY student_id
HAVING COUNT(*) > 1
)
SELECT st.* FROM tmp.student st
JOIN two ON (two.student_id=st.id)
;
For those who want to test, a copy of my generate testdata thingy:
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp;
CREATE TABLE tmp.student
( id INTEGER NOT NULL PRIMARY KEY
, sname VARCHAR
);
CREATE TABLE tmp.club
( id INTEGER NOT NULL PRIMARY KEY
, cname VARCHAR
);
CREATE TABLE tmp.student_club
( student_id INTEGER NOT NULL REFERENCES tmp.student(id)
, club_id INTEGER NOT NULL REFERENCES tmp.club(id)
);
INSERT INTO tmp.student(id)
SELECT generate_series(1,1000)
;
INSERT INTO tmp.club(id)
SELECT generate_series(1,100)
;
INSERT INTO tmp.student_club(student_id,club_id)
SELECT st.id , cl.id
FROM tmp.student st, tmp.club cl
;
DELETE FROM tmp.student_club
WHERE random() < 0.8
;
UPDATE tmp.student SET sname = 'Student#' || id::text ;
UPDATE tmp.club SET cname = 'Soccer' WHERE id = 30;
UPDATE tmp.club SET cname = 'Baseball' WHERE id = 50;
ALTER TABLE tmp.student_club
ADD PRIMARY KEY (student_id,club_id)
;