Выбрать всех пользователей с одной и только одной ролью - многие 2 многие отношения - PullRequest
0 голосов
/ 14 сентября 2011

У меня есть страница в моей административной области, где я хочу запретить пользователям, но я хочу разрешить только запрет пользователям с одной ролью: user .Вот некоторые примеры данных

Пользователь 1 - Роли (запрещены)
Пользователь 2 - Роли (администратор, пользователь)
Пользователь 3 - Роли (закрыты)

Пользователь 4- Роли (пользователь)

Должен быть возвращен только пользователь 4, поскольку он является единственным пользователем, у которого есть роль пользователя и роль пользователя только .Я попытался написать свой собственный запрос ниже, но застрял с тем, как исключить пользователей с более чем просто ролью user .

SELECT users.*, COUNT(*) AS role_count
FROM users
JOIN roles_users
 ON users.id = roles_users.user_id
JOIN roles
 ON roles_users.role_id = roles.id
GROUP BY users.id

Помещение туда WHERE roles.name = 'user' делает role_count = 1

Любая помощь приветствуется.

Ответы [ 3 ]

2 голосов
/ 14 сентября 2011
SELECT users.*, COUNT(*) AS role_count, 
       SUM(case roles.name when 'user' then 1 else 0 end) AS IsUser
FROM users
JOIN roles_users
 ON users.id = roles_users.user_id
JOIN roles
 ON roles_users.role_id = roles.id
GROUP BY users.id
HAVING COUNT(*) = 1
AND SUM(case roles.name when 'user' then 1 else 0 end) = 1
0 голосов
/ 04 ноября 2014

Не следует указывать имя в предложении where во внутреннем запросе, в противном случае будут учитываться только те роли, имя которых 'user'. Сначала выберите пользователей, которые имеют только одну роль, а затем среди этих пользователей проверьте, что их роли - это роль пользователя.

Я верю, что следующее сделает это.

SELECT 
    u.id
    , roles.name
FROM
    users u
    INNER JOIN roles_users ON u.id = roles_users.user_id
    INNER JOIN roles       ON roles_users.role_id = roles.id
WHERE
    exists (
        SELECT
            users.id, COUNT(*) AS role_count
        FROM
            users u2
            JOIN roles_users ON u2.id = roles_users.user_id
        WHERE
            u2.id = u.id
        GROUP BY 
            users.id
        HAVING COUNT(*) = 1
           )
    AND roles.name = 'user'
0 голосов
/ 14 сентября 2011
SELECT * 
  FROM users
 WHERE EXISTS (
               SELECT * 
                 FROM roles_users
                      JOIN roles 
                         ON roles_users.role_id = roles.id               
                WHERE users.id = roles_users.user_id
                      AND roles.name = 'user'
              )
       AND NOT EXISTS (
                       SELECT * 
                         FROM roles_users
                              JOIN roles 
                                 ON roles_users.role_id = roles.id               
                        WHERE users.id = roles_users.user_id
                              AND roles.name <> 'user'
                      );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...