Насколько правильный и безопасный такой запрос 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, который предоставил доступ
  1. Насколько правильный данный запрос?
  2. Насколько безопасный данный запрос?
  3. При больших нагрузках какие могут быть подводные камни в плане производительности?
  4. Либо это вообще не правильная модель построения данной функциональности
    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 шт):

Автор решения: leb

Возможно, тебя заинтересует механизм 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.

→ Ссылка