我有一个游戏,其中我的团队包含许多用户。每个团队中有不同数量的用户,但对于任何团队而言,用户组合使该团队独一无二。
我为此创建了三个数据库表。
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
数组以编程方式填充值。这看起来是否正确?还有另一种方式更好吗?
答案 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[]);