SQL:查找包含列表用户的团队

时间:2013-04-14 00:30:14

标签: sql postgresql relational-division

我有一个游戏,其中我的团队包含许多用户。每个团队中有不同数量的用户,但对于任何团队而言,用户组合使该团队独一无二。

我为此创建了三个数据库表。

 Team    User    TeamUsers
 t_id    u_id    t_id, u_id

如果用户1,4,5和7之前已经在一个团队中,我想知道该团队的团队ID。 SQL会是什么样的?

我尝试过这样的事情:

SELECT t_id FROM teamusers WHERE u_id IN (users[1], ..., users[i])
GROUP BY t_id HAVING COUNT(t_id) = users[].length;

users数组以编程方式填充值。这看起来是否正确?还有另一种方式更好吗?

1 个答案:

答案 0 :(得分:1)

这是关系划分的经典案例。在这个密切相关的问题下,我们汇集了大量的问题: How to filter SQL results in a has-many-through relation

让所有拥有所有球员的球队的一种方式就是你已经拥有的球队。应该是最有效的查询之一。

对于较长的数组,unnest() + JOIN表现更好:

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);

但是对于只有一手牌球员来说,这几乎不重要 要重复使用,您可以创建表函数,而不是在应用程序中构建查询:

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;

呼叫:

SELECT * FROM f_get_teams('{1,4,5,7}'::int[]);