连接子句是实现这一点的唯一方法而 CTE 不能吗?

问题描述

这是我的表(创建于 DB Fiddle),我想找到一个触发事件名称的人(任何人)并检索该用户当天的所有记录。

user_id 日期时间 事件名称 琐碎 trivial_new
001 2020-12-10 10:00:00 1 13
001 2020-12-10 10:00:01 b 9 19
001 2020-12-10 10:00:02 c 3 21
001 2020-12-10 10:00:20 d 6 20
001 2020-12-10 10:00:40 e 2 11
002 2020-12-09 10:00:02 A 2 15
002 2020-12-10 10:00:09 B 4 15
002 2020-12-10 10:00:10 C 9 15
002 2020-12-10 10:00:50 D 0 13

我从 What is a Common Table Expression? 那里学到了 CTE,在那篇文章中,我了解到:

我们可以定义 CTE 作为派生表的替代方案。 CTE 在某种程度上简化了复杂的连接和子查询,提高了查询的可读性。

这里是使用 CTE 的 my attempt

WITH temp AS
(
       SELECT user_id,date_time
       FROM   log_table
       WHERE  binary event_name = "B" limit 1 )
SELECT   *
FROM     log_table
WHERE    user_id = temp.user_id
AND      substring_index(date_time,' ',1) = substring_index(temp.date_time,1)
ORDER BY date_time

它触发了一个错误内容如下:

查询错误错误:ER_BAD_FIELD_ERROR:未知列“temp.user_id” 在'where子句'中

有人告诉我唯一的方法是使用 join,然后我尝试如下:

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 

我想知道我是否能意识到使用 CTE 因为 CTE 简化了复杂的连接

解决方法

您必须将 CTE 添加到 JOIN。

这将是编写查询的正确方法:

WITH temp AS (
  SELECT user_id,date_time
  FROM log_table
  WHERE binary event_name = "B"
  LIMIT 1
)
SELECT l.*
FROM log_table l
JOIN temp ON l.user_id = temp.user_id
    AND SUBSTRING_INDEX(l.date_time,' ',1)  = SUBSTRING_INDEX(temp.date_time,1)
ORDER BY l.date_time

->

| user_id | date_time           | event_name | trivial |
| ------- | ------------------- | ---------- | ------- |
| 002     | 2020-12-10 10:00:02 | A          | 2       |
| 002     | 2020-12-10 10:00:09 | B          | 4       |
| 002     | 2020-12-10 10:00:10 | C          | 9       |
| 002     | 2020-12-10 10:00:50 | D          | 0       |