2016-04-15 58 views
1

我有一组用户和组。用户可以是一个或多个组的一部分,并且组可以有一个或多个用户。所以我得到了user_groups的连接表。创建用户到组的映射,并根据用户组合获取组

有没有一种方法可以根据用户的确切组合找出组的名称?我不积极,如果我已经有适当的结构执行,这是,但这里有两个例子:

ID为1(杰夫)的用户是两个组的一部分,如user_groups表。对于ID为2的组,他是唯一的成员。而另一组ID 4,他是两个成员之一。

我希望能够建立一个查询,如果我只有他的ID,我会知道组名称是GP-B,因为这是映射。如果我有用户ID 14,映射到组4,所以我知道组名是GP-D。

SELECT id, name FROM users;

1, Jeff 
2, John 
3, Mary 
4, Jen 
5, Mike 

SELECT id, name FROM groups;

1, GP-A 
2, GP-B 
3, GP-C 
4, GP-D 

SELECT user_id, group_id FROM user_groups;

1, 2 
1, 4 
2, 3 
4, 1 
4, 4 

我能想出迄今最好的查询是:

SELECT groups.name 
FROM user_groups 
LEFT JOIN groups 
    ON groups.id = user_groups.group_id 
WHERE user_id IN (1,4) 
GROUP BY group_id 
HAVING COUNT(*) = 2; 

这似乎是工作。但是,如果我这样做只是单个用户:

SELECT groups.name 
FROM user_groups 
LEFT JOIN groups 
    ON groups.id = user_groups.group_id 
WHERE user_id IN (1) 
GROUP BY group_id 
HAVING COUNT(*) = 1; 

它结束了拉两组他的一部分,所以东西是不正确我的查询。

+2

不是答案,但这里是一个sql小提琴。 http://sqlfiddle.com/#!9/58596/1 – Jeroen

回答

1

你只需要移动WHERE表达 - user_id IN (1) - 在JOIN条件:

SELECT groups.name 
FROM user_groups 
LEFT JOIN groups 
    ON groups.id = user_groups.group_id AND user_id IN (1) 
GROUP BY group_id 
HAVING COUNT(*) = 1 AND groups.name IS NOT NULL; 

(和HAVING子句中设置一个过滤器,这样你就可以排除NULL群体 - 那些不匹配)

这样你会得到所有行user_groups然后你将能够确保计数将得到你输入的确切数量的记录。

在您的初始查询中,WHERE子句会过滤出一些行,因此您无法真正地正确计算每个组中有多少个成员(因为您排除了那些与您的过滤器不匹配的成员)。

+0

你是一个巫师。是的,那正是我正在寻找的。谢谢! – kenshin9