MySQL / SQLite ВЫБРАТЬ Любой и НЕТ - PullRequest
1 голос
/ 21 июня 2019

Предположим, у меня есть две таблицы:

Пользователь таблицы:

ID           Name
1            User A
2            User B
3            User C
4            User D
5            User E

Разрешение таблицы:

ID           UserID          PermissionName
1            1               read
2            3               read
3            3               write
4            5               read
5            5               write
6            5               admin

Теперь я хочу получить следующие запросы:

1- Все пользователи с правами на запись

SELECT u.* FROM user u, permission p WHERE p.userID = u.id AND p.name = 'write' GROUP BY u.id;

Кажется, все в порядке. Возвращает пользователя 3 и 5.

2- Все пользователи без разрешения на запись

SELECT u.* FROM user u, permission p WHERE p.userID = u.id AND p.name != 'write' GROUP BY u.id;

Возвращает: 1,3,5 Ожидаемое: 1,2,4

Это не работает. Он возвращает каждого пользователя, кроме тех, которые имеют только разрешение на запись. Итак, как я могу заставить это работать в MySQL и SQLite?

3- комбинации обоих

  • Все пользователи с возможностью чтения и записи (3,5)
  • Все пользователи с правами чтения и записи (1)
  • и т.д.

Ответы [ 3 ]

0 голосов
/ 21 июня 2019

Вам нужно присоединиться к таблицам и группировать по user.id. Затем укажите условия в предложении HAVING.
Я предполагаю, что в таблице permission нет дубликатов.
Для 1-го запроса:

select u.id, u.name
from user u inner join permission p
on p.userid = u.id
group by u.id, u.name
having sum(permissionname in ('read', 'write')) = 2

или

select u.id, u.name
from user u inner join permission p
on p.userid = u.id
where permissionname in ('read', 'write')
group by u.id, u.name
having count(permissionname) = 2

и 2-е:

select u.id, u.name
from user u inner join permission p
on p.userid = u.id
group by u.id, u.name
having 
  sum(permissionname = 'read') = 1
  and
  sum(permissionname = 'write') = 0
0 голосов
/ 23 июня 2019

Я нашел рабочее решение, которое можно комбинировать со многими другими фильтрами.Может быть, не самый эффективный способ, но, кажется, все в порядке.

2- Все пользователи без разрешения на запись

SELECT * FROM user WHERE id NOT IN (SELECT userID FROM permission WHERE permission = 'write') ;

3- Все пользователи с чтениеми не пиши

SELECT * FROM user WHERE id NOT IN (SELECT userID FROM permission WHERE permission = 'write') AND id IN (SELECT userID FROM permission WHERE permission = 'read') ;
0 голосов
/ 21 июня 2019

GROUP BY u.id просто объединяет все строки каждого пользователя, которые удовлетворяют условиям WHERE.Поскольку у пользователей 1, 3 и 5 есть разрешения, отличные от write, они возвращаются.

Самый простой способ решить эту проблему - это изменить таблицу разрешений.Например:

Разрешение таблицы:

ID        UserID        CanRead        CanWrite      IsAdmin
1         1             true           false         false
2         3             true           true          false
3         5             true           true          true

И теперь очевидно, что она может стать частью таблицы пользователей:

Пользователь таблицы:

ID     Name        CanRead        CanWrite      IsAdmin
1      User A      true           false         false
2      User B      false          false         false
3      User C      true           true          false
4      User D      false          false         false
5      User E      true           true          true

Так что вам даже не нужна таблица разрешений.Теперь запрос выглядит так:

SELECT * FROM user WHERE CanWrite = 'false'

, что так просто .... но вы думаете, что я обманываю?

Возможно, вы страдали от чрезмерной нормализации призывает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...