Я написал большой запрос MySQL для получения всех разрешений для данного пользователя и недавно обнаружил, что это не работает в более новых версиях MySQL из-за режима ONLY_FULL_GROUP_BY.
Запрос для получения всех предоставленных разрешенийдля данного пользователя:
SELECT
`name`,
`display_name`,
`description`
FROM(
SELECT * FROM (
SELECT
`p`.`id`,
`p`.`name`,
`p`.`display_name`,
`p`.`description`,
MAX(`r`.`priority`),
IFNULL(`up`.`is_granted`, `rp`.`is_granted`) AS `is_granted`
FROM `permissions` AS `p`
LEFT JOIN `user_permissions` AS `up`
ON `up`.`permission` = `p`.`id`
AND `up`.`user` = 1
LEFT JOIN `role_permissions` `rp`
ON `rp`.`permission` = `p`.`id`
AND `rp`.`role` IN(
SELECT
`ur`.`role`
FROM `user_roles` AS `ur`
WHERE `ur`.`user` = 1
)
LEFT JOIN `roles` AS `r`
ON `r`.`id` = `rp`.`role`
GROUP BY `r`.`priority` DESC, `rp`.`permission`, `up`.`permission`
) AS `res`
GROUP BY `res`.`id` ASC
) AS `res`
WHERE `res`.`is_granted` = 1
Это приводит к следующей ошибке на более новых установках MySQL с включенным флагом ONLY_FULL_GROUP_BY (он включен по умолчанию): SQL Error (1055): Expression #5 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'res.MAX(r.priority)' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
.
Я пыталсяполностью переписал запрос, чтобы сделать его более эффективным и работать с включенным флагом, однако он не достигает той же цели, что и первый запрос.
SELECT
u.id AS user_id,
u.email AS user_email,
up.permission AS user_permission_id,
up.is_granted AS user_permission_is_granted,
upp.name AS user_permission_name,
upp.display_name AS user_permission_display_name,
upp.description AS user_permission_description,
ur.role AS role_id,
urr.name AS role_name,
urr.display_name AS role_display_name,
urr.priority AS role_priority,
urp.permission AS role_permission_id,
urp.is_granted AS role_permission_is_granted,
urpp.name AS role_permission_name,
urpp.display_name AS role_permission_display_name,
urpp.description AS role_permission_description
FROM users u
LEFT JOIN user_permissions up
ON up.user = u.id
LEFT JOIN permissions upp
ON upp.id = up.permission
LEFT JOIN user_roles ur
ON ur.user = u.id
LEFT JOIN roles urr
ON urr.id = ur.role
LEFT JOIN role_permissions urp
ON urp.role = ur.role
LEFT JOIN permissions urpp
ON urpp.id = urp.permission
WHERE u.id = 1
Как мне это сделать?Я дал ему пару попыток и не могу найти способ вернуть только строки с наивысшим приоритетом без отключения режима ONLY_FULL_GROUP_BY.
Должен ли я прибегнуть к простому использованию более нового запроса и применению приоритета роли в коде приложенияа не в запросе SQL?
Вот DBFiddle со структурой базы данных и запросом.
Учитывая данные из DBFiddle выше, я хочу, чтобы результирующий набор выгляделнапример:
| user_id | user_email | permission_id | permission_name | permission_display_name | permission_description | is_granted |
| ------- | ----------------- | ------------- | --------------- | ----------------------- | -------------------------------------------------- | ---------- |
| 1 | user1@example.com | 1 | test1 | Test permission 1 | Role permission, should ONLY be granted to user 1 | 1 |
| 1 | user1@example.com | 2 | test2 | Test permission 2 | Role permission, should ONLY be granted to user 1 | 1 |
| 1 | user1@example.com | 3 | test3 | Test permission 3 | Role permission, should ONLY be granted to user 2 | 0 |
| 2 | user2@example.com | 3 | test3 | Test permission 3 | Role permission, should ONLY be granted to user 2 | 1 |
| 1 | user1@example.com | 4 | test4 | Test permission 4 | Role permission, should be granted to user 1 and 2 | 1 |
| 2 | user2@example.com | 4 | test4 | Test permission 4 | Role permission, should be granted to user 1 and 2 | 1 |
| 1 | user1@example.com | 5 | test5 | Test permission 5 | User permission, granted to user 1 | 1 |
| 2 | user2@example.com | 6 | test6 | Test permission 6 | User permission, granted to user 2 | 1 |
Причина, по которой я хочу, чтобы идентификатор разрешения 3 возвращал is_granted = 0
вместо того, чтобы не отображаться в наборе результатов, заключается в том, что пользователь изначально получил разрешение, но затем не получил его от ролиID 2 с более высоким приоритетом.
Этот вопрос не является дубликатом SQL выбирает только строки с максимальным значением в столбце , поскольку он конкретно относится к тому, как мне следует изменить свой запрос наработать в режиме ONLY_FULL_GROUP_BY
.