2013-03-26 38 views
-1

我有一個Users表和Groups表。用戶可以通過'UserInGroup'表格進入多個組,Group可以有'GroupTypeId'。在多對多關係中使用'AND'

[User] 
-------------- 
Id | Name 
1 | Bob 
2 | James 

[UserInGroup] 
----------------- 
UserId | GroupId 
1  1 
1  2 

[Group] 
Id | Name  | TypeId 
------------------------ 
1 | Directors | 1 
2 | IT  | 1 
3 | London | 2 

我想創建一個查詢返回的是兩個「董事會」和「倫敦」(而不是「董事」或「倫敦」),例如用戶。但是,我只希望與AND組中的不同'類型',我想要OR組的相同類型。我可以做每個組類型單獨的表,但我不能,因爲它們是動態創建的。

理想情況下,我希望能夠查詢「董事」,「IT」和「倫敦」中的用戶。

這樣做的最有效方法是什麼?

回答

3

此問題通常被稱爲Relational Division

SELECT a.Name 
FROM [user] a 
     INNER JOIN UserInGroup b 
      ON a.ID = b.UserID 
     INNER JOIN [Group] c 
      ON b.groupID = c.TypeId 
WHERE c.Name IN ('Directors','London') 
GROUP BY a.Name 
HAVING COUNT(*) = 2 

但是,如果一個UNIQUE約束被不上GROUP執行每一個USER,需要DISTINCT關鍵字來篩選出獨特的羣體:

SELECT a.Name 
FROM [user] a 
     INNER JOIN UserInGroup b 
      ON a.ID = b.UserID 
     INNER JOIN [Group] c 
      ON b.groupID = c.TypeId 
WHERE c.Name IN ('Directors','London') 
GROUP BY a.Name 
HAVING COUNT(DISTINCT c.Name) = 2 

OUTPUT 從兩個詢問

╔══════╗ 
║ NAME ║ 
╠══════╣ 
║ Bob ║ 
╚══════╝ 
+0

非常感謝,這非常有幫助。另外,我現在有一個名字來做一些研究。再次感謝。 – Siegemos 2013-03-26 10:45:30

+0

不接受這個答案的原因是什麼?無論如何,你想知道更多,所以我可以改善我的答案。 – 2013-03-26 11:47:54

+0

對不起,非常感謝你的回覆,但我認爲你完全沒有回答我的問題。我的問題是我想在TypeId列不同時使用AND,但是當它相同時使用AND。 所以...我希望「董事」,「IT」和「倫敦」中的所有用戶。 – Siegemos 2013-03-26 11:56:09

0

我得出了以下的解決方案(與幫助,從JW和this article):

SELECT 
    u.Name UserName 
FROM [User] u 
INNER JOIN [UserInGroup] uig 
    ON uig.UserId = u.Id 
INNER JOIN [Group] g 
    ON g.Id = uig.GroupId 
WHERE 
    g.Id IN (1,2,3) -- these are the passed in groupids 
GROUP BY 
    u.Name 
having count(distinct g.TypeId) 
    = (select count(distinct g1.TypeId) 
    from [group] g1 where g1.Id IN (1,2,3)) 

這讓我組關係除以一個鑑別器字段。另一種方法是這樣的:

SELECT a.Name 
FROM [User] a 
    INNER JOIN 
    (
     SELECT b.UserID 
     FROM UserInGroup b 
       INNER JOIN [Group] c 
        ON b.groupID = c.Id 
     WHERE c.Name IN ('Directors','IT') 
     GROUP BY b.UserID 
     HAVING COUNT(DISTINCT c.Name) >= 1 
    ) b ON a.ID = b.UserID 
    INNER JOIN 
    (
     SELECT DISTINCT b.UserID 
     FROM UserInGroup b 
       INNER JOIN [Group] c 
        ON b.groupID = c.Id 
     WHERE c.Name = 'London' 
    ) c ON a.ID = c.UserID 

有了一個額外加入每個GroupTypeId。執行計劃看起來很相似,所以我選擇了第一個選項。