Улучшение запроса для объединения других таблиц в зависимости от значения без объединения - PullRequest
0 голосов
/ 17 января 2020

У меня есть таблица, содержащая следующие данные:

+-----------------+--------------+----------------------+------------+--------------------+-----------+------+---------+---------+-----+------------------------+---------------------+
| notification_id | from_user_id | from_user_auth_level | to_user_id | to_user_auth_level | status_id | type | subject | message | url | timestamp_inserted_utc | timestamp_read_utc  |
+-----------------+--------------+----------------------+------------+--------------------+-----------+------+---------+---------+-----+------------------------+---------------------+
|               1 | NULL         | NULL                 |          1 |                  1 |         0 |    2 | test    | test    | url | 2010-10-10 00:00:00    | 2011-10-10 00:00:00 |
|               2 | 2            | 5                    |          1 |                  1 |         0 |    2 | test    | test    | url | 2010-10-10 00:00:00    | 2011-10-10 00:00:00 |
|               3 | 3            | 5                    |          1 |                  1 |         0 |    2 | test    | test    | url | 2010-10-10 00:00:00    | 2011-10-10 00:00:00 |
|               4 | 2295         | 4                    |          1 |                  1 |         0 |    2 | test    | test    | url | 2010-10-10 00:00:00    | 2011-10-10 00:00:00 |
|               5 | 10           | 1                    |          1 |                  1 |         0 |    2 | test    | test    | url | 2010-10-10 00:00:00    | 2011-10-10 00:00:00 |
+-----------------+--------------+----------------------+------------+--------------------+-----------+------+---------+---------+-----+------------------------+---------------------+

А затем у меня есть несколько других таблиц, таких как «пользователи», «компании», «организации», ... и т. Д. c.

Мне нужно иметь возможность получать имя пользователя, пол и изображение каждого уведомления (на основе from_user_id и from_user_auth_level).

Но проблема заключается в том, что эта информация находится в в разных местах, в зависимости от того, что такое user_auth_level.

Например: если мой пользователь "обычный" пользователь, его auth_level будет равен 1. И изображение будет находиться в моей таблице "users", а также пол применимо. Но если у пользователя auth_level == 5, это означает, что он является организацией. В этом случае пол не применим, и изображение находится в таблице «организация», через пользователя его необходимо связать с user_roles, а затем с организацией.

И так далее для каждого типа пользователя, все они требуют разных объединений.

Я создал рабочий запрос, но он везде использует UNION, и я прочитал, что он не самый лучший использовать по соображениям производительности, поэтому я надеюсь, что кто-то может помочь мне улучшить этот запрос с учетом производительности:

                SELECT n.*, NULL as username, NULL as gender, NULL as picture
                FROM notification as n
                WHERE n.from_user_auth_level IS NULL
                AND n.to_user_id = $userid
                UNION
                SELECT n.*, u.username, u.gender as gender, u.profile_picture as picture
                FROM notification as n
                LEFT JOIN users AS u ON n.from_user_id = u.user_id
                WHERE n.from_user_auth_level = 1
                AND n.to_user_id = $userid
                UNION
                SELECT n.*, u.username, NULL as gender, c.logo as picture
                FROM notification as n
                LEFT JOIN users AS u ON n.from_user_id = u.user_id
                LEFT JOIN user_companies AS uc on u.user_id = uc.user_id
                LEFT JOIN company as c on uc.company_id = c.company_id
                WHERE n.from_user_auth_level = 4
                AND n.to_user_id = $userid
                UNION
                SELECT n.*, u.username, NULL as gender, o.logo as picture
                FROM notification as n
                LEFT JOIN users AS u ON n.from_user_id = u.user_id
                LEFT JOIN user_roles as ur on u.user_id = ur.user_id
                LEFT JOIN organization as o on ur.org_id = o.org_id
                WHERE n.from_user_auth_level = 5
                AND n.to_user_id = $userid
                UNION
                SELECT n.*, u.username, NULL as gender, o.logo as picture
                FROM notification as n
                LEFT JOIN users AS u ON n.from_user_id = u.user_id
                LEFT JOIN user_roles as ur on u.user_id = ur.user_id
                LEFT JOIN organization as o on ur.org_id = o.org_id
                WHERE n.from_user_auth_level = 7
                AND n.to_user_id = $userid
                UNION
                SELECT n.*, u.username, NULL as gender, NULL as picture
                FROM notification as n
                LEFT JOIN users AS u ON n.from_user_id = u.user_id
                WHERE n.from_user_auth_level = 9
                AND n.to_user_id = $userid"

После того, как я получу этот результат, я использую PHP, чтобы упорядочить результаты на основе timestamp_inserted_ut c, поскольку с помощью UNION невозможно получить правильные результаты.

Ответы [ 2 ]

1 голос
/ 17 января 2020

Предлагаемые индексы (большинство из них "покрывают"):

n:  (from_user_auth_level, to_user_id, from_user_id)
u:  (user_id, username, profile_picture, gender)
o:  (org_id, logo)
ur:  (org_id, user_id)
c:  (company_id, logo)
uc:  (company_id, user_id)

(Они могут даже ускорить ответ Тесона.)

1 голос
/ 17 января 2020

Я бы использовал таблицу уведомлений в качестве базы и использовал условные внешние объединения как:

select 
  n.*,t1.gender, t2.orgNo 
from 
  notifications n
left outer join table1 t1 on (n.auth=1 and more join)
left outer join table2 t2 on (n.auth=2 and more..)

У вас будет больше столбцов, но их имя будет иметь смысл, и вы можете объединиться на уровне приложения.

...