2013-04-14 50 views
1

我有一個包含多個用戶的團隊的遊戲。每個團隊的用戶數量不同,但對於任何一個團隊來說,用戶組合都會使團隊獨一無二。SQL:查找包含列表用戶的團隊

我爲此創建了三個數據庫表。

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

你如何處理隨時間而改變嗎?我們如何知道用戶是同一個團隊的成員*?成員中的每一個變化是否會自動創建一個* new *團隊(不同的't_id')? –

+0

是的用戶更改創建一個新的團隊。如果你玩過那款遊戲,它的作用就像SC2的組合一樣嗎?如果你和一個創建團隊的人一起玩。 –

回答

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[]); 
+0

非常感謝您的回答! –