最近我遇到了一个有趣的问题.让我们添加一些表,即User,Group及其Join表User_Group.以下是表格的虚拟表示
用户
user_id | user_name
1 | a
2 | b
3 | c
组
group_id | group_code
1 | G1
2 | G2
3 | G3
USER_GROUP
userid | groupid | exclusion
1 | 1 | 0
1 | 2 | 0
2 | 1 | 1
那么问题是获取他可以访问的用户的组列表.
组中用户访问的一般假设是:
>如果用户在User_group连接表中没有条目,则用户可以访问该条目
所有组(即G1,G2和G3)
>如果用户在User_Group中有条目
排除0然后该用户只能访问该组(用户1具有
访问G1和g2)
>如果用户在User_Group中具有排除条目
1然后该用户在该组中没有访问权限但他有权访问
其他所有其他组(用户2仅在g1上被拒绝,应该有
访问G2和G3)
这是查询案例1& 3但案例2失败.
SELECT g.id, g.code, ug.user_groups_id, ug.exclusion FROM group g
LEFT JOIN user_group ug ON ug.group_id = g.id
AND ug.user_id = 1 -- works for user 2 and 3 but fails for user 1
WHERE (ug.exclusion = 0 OR ug.exclusion IS NULL)
请建议我们是否可以使用单个查询获取组列表
最佳答案 有趣的问题.
您可以通过生成所有用户和所有组的列表(使用交叉连接)来解决此问题.然后使用左连接匹配回已知的组列表.那么逻辑就是:
>案例1是在没有匹配时使用所有组.
>案例2仅使用匹配的组.
>案例3仅使用不匹配的组.
这是查询:
select u.userid,
(case when max(ug.exclusion) is null -- all groups
then group_concat(g.groupcode)
when max(ug.exclusion) = 0 -- only those included
then group_concat(case when ug.groupid is not null then g.groupcode end)
when max(ug.exclusion) = 1 -- exclude these
then group_concat(case when ug.groupid is null then g.groupcode end)
end)
from users u cross join
groups g left join
user_groups ug
on u.userid = ug.userid and g.groupid = ug.groupid
group by u.userid;
请注意,这仅使用聚合中的排除标志 – 基本上假设它在user_groups中的所有行上都相同.实际上,此标志可以在用户级别而不是在user_groups级别.该假设与样本数据和问题的解释一致.