如何编写查询以从关系中获取唯一元素

时间:2018-04-04 17:34:24

标签: mysql sql

我有2个具有多对多关系的实体。用户 - Roles_Users - 角色

如何编写一个查询,向我返回只有一个角色的所有用户,即角色名称" customer"。我写了这样的话:

SELECT `users`.* FROM `users`
INNER JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id`
INNER JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id`
WHERE roles.name not in ('admin' , 'sac', 'superadmin',  'customer_service' ,  'supplier');

但它仍然带给我的用户不仅仅是角色'客户'。

我需要的用户只有'客户'没有别的

4 个答案:

答案 0 :(得分:1)

这就是我要解决的问题:

SELECT `users`.* 
FROM `users`
WHERE id IN
 (
   SELECT `roles_users`.`user_id`
   FROM `roles_users`
   INNER JOIN `roles`
   ON `roles`.`id` = `roles_users`.`role_id`
   GROUP BY `roles_users`.`user_id`
   HAVING COUNT(*) = 1                 -- only a single role
      AND MAX(roles.name) = 'customer' -- and this role is 'customer'
 ) 

顺便说一句,没有必要使用所有这些反对:

SELECT * 
FROM users
WHERE id IN
 (
   SELECT roles_users.user_id
   FROM roles_users
   JOIN roles
     ON roles.id = roles_users.role_id
   GROUP BY roles_users.user_id
   HAVING COUNT(*) = 1                 -- only a single role
      AND MAX(roles.name) = 'customer' -- and this role is 'customer'
 ) 

这不容易阅读(和写)吗?

答案 1 :(得分:0)

直接比较角色名称,因为使用in可以获得其他非必需值

   SELECT `users`.* FROM `users` INNER JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id` INNER JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id` WHERE roles.name ='customer'

答案 2 :(得分:0)

为什么不直视具有特定角色的用户?

SELECT `users`.* FROM `users` 
JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id` 
JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id` 
WHERE `roles`.name  = 'customer';

答案 3 :(得分:0)

在WHERE子句中使用NOT EXISTS子查询:

SELECT u.*
FROM users u
INNER JOIN roles_users ru ON ru.user_id = u.id
INNER JOIN roles r ON r.id = ru.role_id
WHERE r.name = 'customer'
  AND NOT EXISTS (
    SELECT *
    FROM roles_users ru1
    WHERE ru1.user_id  = ru.user_id
      AND ru1.role_id <> ru.role_id
  )

NOT EXISTS条件将确保不会为用户分配任何其他角色。

更短但更慢的解决方案可能是:

SELECT u.*
FROM users u
INNER JOIN roles_users ru ON ru.user_id = u.id
INNER JOIN roles r ON r.id = ru.role_id
GROUP BY u.id
HAVING GROUP_CONCAT(r.name) = 'customer'