-1

私はUsersテーブルとテーブルを持っていGroupsます。ユーザーは「UserInGroup」テーブルを介して複数のグループに属することができ、グループは「GroupTypeId」を持つことができます。

[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

たとえば、「Directors」または「London」ではなく、「Directors」と「London」の両方にいるユーザーを返すクエリを作成したいと思います。ただし、異なる「タイプ」のグループのANDのみを実行し、同じタイプのグループのORを実行します。グループタイプごとに個別のテーブルを作成することはできますが、動的に作成されるため、できません。

理想的には、「Directors」または「IT」および「London」にいるユーザーにクエリを実行できるようにしたいです。

これを行う最も効率的な方法は何ですか?

4

2 に答える 2

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制約が適用されていない場合は、一意のグループを除外するためにキーワードが必要です。GROUPUSERDISTINCT

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

両方のクエリからの出力

╔══════╗
║ NAME ║
╠══════╣
║ Bob  ║
╚══════╝
于 2013-03-26T00:34:01.307 に答える
0

私は次の解決策に到達しました(JWとこの記事の助けを借りて):

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ごとに追加の結合があります。実行プランは似ているので、最初のオプションを選択しました。

于 2013-03-27T09:16:23.327 に答える