代码之家  ›  专栏  ›  技术社区  ›  Lerner Zhang

这个条件在外连接中会比where子句快吗?

  •  0
  • Lerner Zhang  · 技术社区  · 4 年前

    这是我的桌子

    CREATE TABLE log_table (
      `user_id` VARCHAR(5),
      `date_time` DATETIME,
      `event_name` VARCHAR(10),
      `trivial` int
    );
    
    INSERT INTO log_table
      (`user_id`, `date_time`, `event_name`, `trivial`)
    VALUES
      ('001', '2020-12-10 10:00:02', 'c', 3),
      ('001', '2020-12-10 10:00:01', 'b', 9),
      ('001', '2020-12-10 10:00:40', 'e', 2),
      ('001', '2020-12-10 10:00:20', 'd', 6),
      ('001', '2020-12-10 10:00:00', 'a', 1),
      ('002', '2020-12-09 10:00:10', 'C', 9),
      ('002', '2020-12-10 10:00:50', 'D', 0),
      ('002', '2020-12-10 10:00:02', 'A', 2),
      ('002', '2020-12-10 10:00:09', 'B', 4);
    

    (创建于 DB Fiddle )

    我想找到一个人(任何人)触发了一个事件名称,并检索该用户当天的所有记录。

    日期/时间 事件名称 琐碎的 琐碎的新事物
    001 A. 13
    001 2020-12-10 10:00:01 19
    2020-12-10 10:00:02 C 21
    2020-12-10 10:00:20 D 6.
    001 2020-12-10 10:00:40 2. 11
    002 A. 15
    002 15
    2020-12-10 10:00:10 C
    2020-12-10 10:00:50 D 13

    SELECT t_left.*
    FROM   log_table AS t_left
           RIGHT JOIN (SELECT user_id,
                              date_time
                       FROM   log_table
                       WHERE  BINARY event_name = 'B'
                       LIMIT  1) AS t_right
                   ON t_left.user_id = t_right.user_id
                      AND Substring_index(t_left.date_time, ' ', 1) =
                          Substring_index(t_right.date_time, ' ', 1)
    ORDER  BY date_time 
    

    在右边的表中,只有一条记录满足 event_name B 2020-12-10 ,删除具有不同ID的其他用户, 001 ,以及发生事件的同一个人的记录 2020-12-10 .

    一切正常。

    here ):

    SELECT t_left.*
    FROM   log_table AS t_left
           RIGHT JOIN (SELECT user_id,
                              date_time
                       FROM   log_table
                       WHERE  BINARY event_name = 'B'
                       LIMIT  1) AS t_right
                   ON t_left.user_id = t_right.user_id
    WHERE  Substring_index(t_left.date_time, ' ', 1) =
           Substring_index(t_right.date_time, ' ', 1)
    ORDER  BY date_time 
    

    在本例中,我只是按一个条件联接表,并过滤该用户的日期以获得正确的记录。

    我读了一些答案 here here here

    有什么在线平台可以比较速度吗?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Rick James diyism    4 年前

    ON 应该用来说明表之间的关系。

    WHERE 应用于过滤。

    对于平原 JOIN INNER JOIN ),它们的实现方式相同。

    对于左/右,它们可能会有很大的不同。

        2
  •  0
  •   FanoFN    4 年前

    如果假设第二个查询是最终的查询结构,则不需要使用 RIGHT JOIN 再说了,这尤其正确,因为你要匹配 WHERE 而是在 ON .. 有效地取消右连接(或左连接)。实际上,由于您对只提取右侧表的特定数据的子查询执行右联接,因此几乎没有任何理由执行右联接,如果改为执行左联接,结果会有更多差异。另外,根据我的经验, JOIN INNER JOIN

    另一件事是,在性能方面,索引有很大的不同。在您当前的示例中,没有索引,因此我建议您这样做。我从@Rick James'那里学到了很多关于索引的知识 page here

    这是一把基于你的示例日期的小提琴,包括你最初的尝试和其他一些:

    1. RIGHT JOIN .. ON ... AND
    2. RIGHT JOIN .. ON ... WHERE
    3. LEFT JOIN .. ON ... AND
    4. LEFT JOIN .. ON ... WHERE
    5. 添加索引
    6. EXPLAIN 索引前后。

    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1b244deb6fad0dda0bf4aaf701e6bac2

    附言:在小提琴,我改变了日期提取使用 DATE()