【问题标题】:Joins on the same table在同一张表上连接
【发布时间】:2019-07-26 04:47:17
【问题描述】:

有没有更有效的方法来做到这一点?我一直在想我错过了什么。谢谢

SELECT DISTINCT eventId 
FROM event_tags_map 
WHERE tagId in (
    SELECT tagId FROM event_tags_map WHERE eventId=114778
) ORDER BY RAND() LIMIT 5;

我在同一张桌子上打了两次,我想知道我是否可以更快地获得相同的结果。

表结构:

mysql> describe event_tags_map;
+---------+------------------+------+-----+---------+-------+
| Field   | Type             | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| eventId | int(10) unsigned | NO   | PRI | NULL    |       |
| tagId   | int(10) unsigned | NO   | PRI | NULL    |       |
+---------+------------------+------+-----+---------+-------+

索引:

mysql> show index from event_tags_map;
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table          | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| event_tags_map |          0 | PRIMARY  |            1 | eventId     | A         |      302032 |     NULL | NULL   |      | BTREE      |         |               |
| event_tags_map |          0 | PRIMARY  |            2 | tagId       | A         |      604065 |     NULL | NULL   |      | BTREE      |         |               |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.02 sec)

【问题讨论】:

    标签: mysql sql join mysql-python


    【解决方案1】:

    看来您需要以一种或另一种方式引用原始表格两次。

    我建议不要使用 IN 条件,它的可扩展性不是很好,并且具有各种反直觉的行为。

    我的第一个选项是使用带有EXISTS 条件的相关子查询。这通常是检查某物存在...

    的最有效方法
    SELECT DISTINCT eventId 
    FROM event_tags_map m
    WHERE EXISTS (
        SELECT 1 FROM event_tags_map m1 WHERE m1.eventId = 114778 AND m1.tagId = m.tagId
    )
    ORDER BY RAND() LIMIT 5;
    

    另一种选择是使用 self-INNER JOIN:

    SELECT DISTINCT eventId 
    FROM event_tags_map m
    INNER JOIN event_tags_map m1 ON m1.eventId = 114778 AND m1.tagId = m.tagId
    ORDER BY RAND() LIMIT 5;
    

    两种解决方案都应该能够利用event_tags_map(eventId, tagId) 上的复合索引。

    【讨论】: