SQL:Where IN查询

时间:2011-12-18 20:21:41

标签: mysql sql

因此在数据库中,有一个名为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

6 个答案:

答案 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)