mysql - 改进查询以根据没有联合的值连接其他表

标签 mysql sql performance query-performance

我有一个包含以下数据的表:

+-----------------+--------------+----------------------+------------+--------------------+-----------+------+---------+---------+-----+------------------------+---------------------+
| 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 |
+-----------------+--------------+----------------------+------------+--------------------+-----------+------+---------+---------+-----+------------------------+---------------------+

然后我还有一些其他表,例如“用户”、“公司”、“组织”等。

我需要能够获取每个通知的用户名、性别和图像(基于 from_user_id 和 from_user_auth_level)。

但问题在于,该信息驻留在不同的位置,具体取决于 user_auth_level 是什么。

例如:如果我的用户是“常规”用户,则他的 auth_level 将为 1。并且图像将驻留在我的“用户”表中,并且性别适用。 但如果用户的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_utc 对结果进行排序,因为不可能通过 UNION 获得正确的结果。

最佳答案

我将使用通知表作为基础,并将条件外连接用作:

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..)

您将拥有更多列,但它们的名称有意义,并且您可以在应用程序级别进行合并。

关于mysql - 改进查询以根据没有联合的值连接其他表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59789496/

相关文章:

mysql - 在 UNION 中使用 Order By NULL

php json_encode 返回 0 ,有时为零值

java - JDBC 领域找不到 mysql 驱动程序

php - 多个sql查询的单个查询

sql - 根据交易添加期末余额列(收入-支出)

c# - log2(int) 和 log2(float) 的最快实现

php - 如何使用 PHP 打破 MySQL 查询的束缚?

sql - 雪花: SQL Query to identify all the different users with the same ID from the same or multiple tables

performance - 最长公共(public)子序列算法调试性能瓶颈

c - 性能比较 : Sqlite SELECT f FROM t WHERE rowid = %q VS. 标准。 C Fopen + Fseek