This is a classical case of relational division. We have assembled a whole arsenal of queries under this closely related question:
How to filter SQL results in a has-many-through relation
One way to get all teams that have all given players would be what you already have. Should be among the most efficient queries.
For longer arrays, unnest()
+ JOIN
performs better:
SELECT t_id
FROM (SELECT unnest($users) AS u_id) u
JOIN team_users USING (u_id)
GROUP BY 1
HAVING count(*) = array_length($users, 1);
But for just a hand full of players, it hardly matters.
For repeated use, instead of building the query in your app, you can create a table function:
CREATE OR REPLACE FUNCTION f_get_teams(_users int[])
RETURNS SETOF int AS
$func$
SELECT t_id
FROM (SELECT unnest($1) AS u_id) u
JOIN team_users USING (u_id)
GROUP BY 1
HAVING count(*) = array_length($1, 1);
$func$ LANGUAGE SQL STRICT;
Call:
SELECT * FROM f_get_teams('{1,4,5,7}'::int[]);