Насколько правильный и безопасный такой запрос SQL к БД
Есть две таблицы. Таблица 1 - список групп. Таблица 2 - таблица, которая описывает параметры совместного доступа, где скомбинированные виды доступа (DATE, GROUP), в зависимости от поля access_type.
Нужно выбрать все записи из таблицы 1 для определенного юзера А=>$uid (плюс фильтр по опр. дате $date), а ТАКЖЕ все записи юзера Б, к которым юзер Б предоставил доступ юзеру А. Но записи из таблицы 2 не должны быть в результате!
Вот часть таблицы 1 user_road_group
id | uid | date | name |
---|---|---|---|
1 | 1 | 2010-10-1 | Group1 |
2 | 1 | 2010-10-1 | Group2 |
3 | 5 | 2010-10-3 | Group3 |
4 | 5 | 2010-10-4 | Group4 |
Таблица 2 user_road_uaccess - конфигурация доступа
access_type - тип доступа (DATE - ко всем группам опр. даты, GROUP - только к опр. группе)
main_uid - юзер, который предоставил доступ
permitted_uid - юзер, который получил доступ
Также несколько комбинаций записей в пример
id | access_type | access_param | main_uid | permitted_uid | example |
---|---|---|---|---|---|
1 | DATE | 2020-10-1 | 1 | 5 | Доступ юзера 5 к записям юзера 1 ко всем записям на определенную дату (2020-10-1) |
2 | GROUP | 3 | 5 | 1 | Доступ юзеру 1 к группе ID==3 юзера 5, который предоставил доступ |
- Насколько правильный данный запрос?
- Насколько безопасный данный запрос?
- При больших нагрузках какие могут быть подводные камни в плане производительности?
- Либо это вообще не правильная модель построения данной функциональности
SELECT DISTINCT `user_road_group`.*
FROM `user_road_uaccess`, `user_road_group`
WHERE
(
`user_road_uaccess`.`permitted_uid` = $uid
AND `user_road_uaccess`.`access_revoked` = 0
AND
(
(
`user_road_uaccess`.`access_type` = 'DATE'
AND user_road_uaccess.access_param = user_road_group.date
)
OR
(
`user_road_uaccess`.`access_type` = 'GROUP'
AND user_road_uaccess.access_param = user_road_group.id
)
)
AND user_road_group.date = $date
)
OR
(
user_road_group.date = $date
AND `user_road_group`.`uid` = $uid
)
ORDER BY `user_road_group`.`deleted`
Ответы (1 шт):
Возможно, тебя заинтересует механизм JOIN
.
Запросы с ним лучше читаемы. Уверен, что ещё и оптимизированы (должны же быть).
+-----+-----+------------+------------+
| _id | uid | day | name |
+-----+-----+------------+------------+
| 1 | 1 | 2010-10-01 | Group1 |
| 2 | 1 | 2010-10-01 | Group2 |
| 3 | 5 | 2010-10-03 | Group3 |
| 4 | 5 | 2010-10-04 | Group4 |
| 5 | 4 | 2024-11-21 | Group5 |
| 6 | 3 | 2024-11-21 | Group6 |
| 7 | 6 | 2024-11-21 | Group7 |
| 8 | 4 | 2024-11-21 | Group99 |
| 9 | 3 | 2024-11-21 | Group43141 |
| 10 | 2 | 2024-11-21 | Group0 |
+-----+-----+------------+------------+
SELECT uid, day, name
-> FROM user_road_group
-> RIGHT JOIN user_road_uaccess ON permitted_uid=uid OR main_uid=uid
-> GROUP BY name
-> ;
+------+------------+--------+
| uid | day | name |
+------+------------+--------+
| 1 | 2010-10-01 | Group1 |
| 1 | 2010-10-01 | Group2 |
| 5 | 2010-10-03 | Group3 |
| 5 | 2010-10-04 | Group4 |
+------+------------+--------+
4 rows in set (0,001 sec)
В примере я немного схитрил оператором GROUP BY
-- без него каждое вхождение продублируется (permitted_uid
и main_uid
). И, конечно, предполагатеся, что name
будет UNIQUE
.
О работе с оператором JOIN
очень хорошо рассказывается на сайте Metanit.com.