我有一个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
我想创建一个查询来返回例如“导演”和“伦敦”(而不是“导演”或“伦敦”)的用户。但是,我只想要AND组的不同'Type',我想要OR组相同的类型。我可以为每个组类型设置一个单独的表,但我不能动态创建它们。
理想情况下,我希望能够查询“董事”或“IT”和“伦敦”的用户。
最有效的方法是什么?
答案 0 :(得分: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
个关键字来过滤掉唯一群组:
╔══════╗
║ NAME ║
╠══════╣
║ Bob ║
╚══════╝
来自两个查询的输出
{{1}}
答案 1 :(得分:0)
我得到了以下解决方案(在J W和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添加额外的连接。执行计划看起来很相似,所以我选择了第一个选项。