因此在数据库中,有一个名为roles_users的表。这包含用户拥有的所有角色。这里有两列:user_id,role_id。
没有额外角色的普通用户在此表中有1行。这一行有role_id 1。
管理员用户,在此表中有2行。一个使用role_id 1,另一行使用role_id 2
像这样:
user_id role_id
88 1
88 2
99 1 // Only one row with that user_id, so he's a user
现在我试图计算存在多少用户/管理员/卖家/合作伙伴。
卖家有3行,其中一行有role_id 1,role_id 2和role_id 3.
合作伙伴有role_id 1,role_id 4
所以我试过这个:
SELECT user_id FROM roles_users WHERE role_id IN (1) // MEMBERS ONLY
SELECT user_id FROM roles_users WHERE role_id IN (1,2) // ADMIN
SELECT user_id FROM roles_users WHERE role_id IN (1,2,3) // SELLER
SELECT user_id FROM roles_users WHERE role_id IN (1,4) // PARTNERS
但是这些查询无法正常运行。他们给了我一个超过预期的计数。我相信这是因为它不会排除任何行,
我的意思是在查询时应该查找role_id 1,对于成员来说,它还包括合作伙伴,管理员,卖家,因为它只检查是否具有行role_id 1的任何内容,并且就是这样。
那我怎么能这样做呢?因此,当它关注成员时,它还应该确保user_id不再包含其他role_ids的行,例如2,3,4
答案 0 :(得分:1)
group_concat
就是你想要的:
select
case roles
when '1' then 'members'
when '1,2' then 'admins'
when '1,2,3' then 'sellers'
when '1,4' then 'partners'
else 'uh??'
end role,
count(user_id) nr_users from (
select user_id, group_concat(role_id order by role_id separator ',') roles
from roles_users
group by user_id
)
group by role
order by role;
顺便说一句,您可以使用位掩码更有效地存储角色。优点:每个用户ID只有一列。缺点:难以构建查询...
答案 1 :(得分:0)
这将为您提供表中所有权限组合及其计数
SELECT
COUNT(*) AS num
GROUP_CONCAT(role_id ORDER BY role_id) AS privilegeset
FROM roles_users
GROUP BY user_id
答案 2 :(得分:0)
关于卖家和合作伙伴:
根据我的理解,卖家是唯一可以拥有role_id = 3
且合作伙伴是唯一可以拥有role_id = 4
的人,对吗?
如果是,找到卖家和合作伙伴非常容易:
SELECT user_id FROM roles_users WHERE role_id = 3 // SELLER
SELECT user_id FROM roles_users WHERE role_id = 4 // PARTNERS
答案 3 :(得分:0)
这是一个基于连接的解决方案,可以在任何SQL上运行。
SELECT user_id FROM roles_users RU0
LEFT JOIN roles_users RU1 ON RU0.user_id = RU1.user_id AND RU1.role_id = 1
LEFT JOIN roles_users RU2 ON RU0.user_id = RU2.user_id AND RU2.role_id = 2
LEFT JOIN roles_users RU3 ON RU0.user_id = RU3.user_id AND RU3.role_id = 3
LEFT JOIN roles_users RU4 ON RU0.user_id = RU4.user_id AND RU4.role_id = 4
WHERE RU1.user_id IS NOT NULL -- should have role 1
AND RU2.user_id IS NULL -- should NOT have role 2
AND RU3.user_id IS NULL -- should NOT have role 3
AND RU4.user_id IS NOT NULL -- should have role 4
只需更改where子句中的“IS NULL”和“IS NOT NULL”即可更改您希望用户拥有或不拥有的角色。
答案 4 :(得分:0)
不是最优雅,而是一个开始
SELECT user_id
,CASE WHEN (role1 > 0 AND 0 = role2 AND 0 = role3 AND 0 = role4) THEN 'MEMBER'
WHEN (role1 > 0 AND role2 > 0 AND 0 = role3 AND 0 = role4) THEN 'ADMIN'
WHEN (role1 > 0 AND role2 > 0 AND role3 > 0 AND 0 = role4) THEN 'SELLER'
WHEN (role1 > 0 AND 0 = role2 AND 0 = role3 AND role4 > 0) THEN 'PARTNER'
ELSE 'Something else'
END AS type
FROM (
SELECT user_id
,SUM( CASE role_id WHEN 1 THEN 1 ELSE 0 END) AS role1
,SUM( CASE role_id WHEN 2 THEN 1 ELSE 0 END) AS role2
,SUM( CASE role_id WHEN 3 THEN 1 ELSE 0 END) AS role3
,SUM( CASE role_id WHEN 4 THEN 1 ELSE 0 END) AS role4
FROM roles_users
GROUP BY user_id
) x
编辑:我想这是回答错误的问题,它显示了每个用户的类型。
答案 5 :(得分:0)
这是使用INTERSECT和MINUS的解决方案。可悲的是,这些还没有得到MySQL的支持,但也许有人会觉得这很有用。
- 查找角色为1的用户
SELECT user_id FROM
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1)
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1)
- 查找角色1和2的用户
SELECT user_id FROM
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1
INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 2)
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,2)
- 使用角色1,2,3
查找用户SELECT user_id FROM
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1
INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 2
INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 3)
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,2,3)
- 使用角色1,4找到用户
SELECT user_id FROM
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1
INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 4)
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,4)