SQL 查询与最近(及时)的前一个数据库条目的时间差
SQL query to get time diff from closest (in time) previous db entry
我有 2 个数据库 table 来处理问题跟踪系统(如 Zendesk 或 Jira):一个 tickets
(父 table)和一个 messages
(子table,存储一张票的每条消息)。像这样:
tickets
table:
id
created_at
messages
table:
id
created_at
ticket_id
text
source (could be either 'company' or 'client')
我想制作一个 SQL 查询,该查询将生成票证消息,其中每一行都涉及一条 'company' 消息以及自上次 'client' 消息以来的时间延迟。 “时间延迟”是指:
created_at
来自 'company' 消息减去 created_at
来自之前的 'client' 消息
请注意,可以连续发送多个 'company' 或 'client' 条消息。
因此,如果工单(ID 为 4528)有这些消息(按时间顺序):
- 'client' message (id 1)
- 'company' message (id 2)
- 'client' message (id 3)
- 'company' message (id 4)
- 'company' message (id 5)
我希望 SQL 查询产生如下内容:
ticket id
message id
Time diff since previous 'client' message
4528
2
time diff between 2 and 1
4528
4
time diff between 4 and 3
4528
5
time diff between 5 and 3
感谢任何帮助。
这是一个例子。 Fiddle
只有 join
company
行具有适用的 client
行具有先前的 created_at
值。然后按相反的时间顺序为每个 company
的这些 client
行分配一个 row_number
。选择 n = 1
以获得每个 company
行的最近前 client
行。
我们可以在 PARTITION BY
子句中添加 ticket_id
来处理多张工单。
SQL:
WITH cte1 (id, ticket_id, text, ts, client_id, ts2, n, dt) AS (
SELECT m1.id, m1.ticket_id, m1.text, m1.created_at
, m2.id AS last_client_id, m2.created_at
, ROW_NUMBER() OVER (PARTITION BY m1.id, m1.ticket_id ORDER BY m2.id DESC) AS n
, m1.created_at - m2.created_at AS dt
FROM messages AS m1
LEFT JOIN messages AS m2
ON m1.ticket_id = m2.ticket_id
AND m2.source = 'client'
AND m2.created_at < m1.created_at
WHERE m1.source = 'company'
)
SELECT * FROM cte1 WHERE n = 1
;
我没有注意到原始问题上的 MySQL
标签,只注意到 postgresql
标签。 SQL两者的结构基本相同,只是在时差计算上稍作调整。
这也是 MariaDB/MySQL 的最新版本 (Fiddle):
WITH cte1 (id, ticket_id, text, ts, client_id, ts2, n, dt) AS (
SELECT m1.id, m1.ticket_id, m1.text, m1.created_at
, m2.id AS last_client_id, m2.created_at
, ROW_NUMBER() OVER (PARTITION BY m1.id, m1.ticket_id ORDER BY m2.id DESC) AS n
, ABS(timestampdiff(minute, m1.created_at, m2.created_at)) AS dt
FROM messages AS m1
LEFT JOIN messages AS m2
ON m1.ticket_id = m2.ticket_id
AND m2.source = 'client'
AND m2.id < m1.id
WHERE m1.source = 'company'
)
SELECT * FROM cte1 WHERE n = 1
;
旧版本的 MySQL 或 Maria 将不支持 WITH clause
或 Window Function
。还是可以的。
设置:
CREATE TABLE messages (
id int
, created_at timestamp
, ticket_id int
, text varchar(30)
, source varchar(20)
);
INSERT INTO messages (id, ticket_id, source, text, created_at) VALUES
(1, 1234, 'client' , 'message 01', current_timestamp + INTERVAL '+1 HOUR')
, (2, 1234, 'company', 'message 02', current_timestamp + INTERVAL '+2 HOUR')
, (3, 1234, 'client' , 'message 03', current_timestamp + INTERVAL '+3 HOUR')
, (4, 1234, 'company', 'message 04', current_timestamp + INTERVAL '+4 HOUR')
, (5, 1234, 'company', 'message 05', current_timestamp + INTERVAL '+5 HOUR')
;
MySQL/MariaDB 的 INTERVAL 语法略有不同:
INSERT INTO messages (id, ticket_id, source, text, created_at) VALUES
(1, 1234, 'client' , 'message 01', current_timestamp + INTERVAL 1 HOUR)
, (2, 1234, 'company', 'message 02', current_timestamp + INTERVAL 2 HOUR)
, (3, 1234, 'client' , 'message 03', current_timestamp + INTERVAL 3 HOUR)
, (4, 1234, 'company', 'message 04', current_timestamp + INTERVAL 4 HOUR)
, (5, 1234, 'company', 'message 05', current_timestamp + INTERVAL 5 HOUR)
;
我有 2 个数据库 table 来处理问题跟踪系统(如 Zendesk 或 Jira):一个 tickets
(父 table)和一个 messages
(子table,存储一张票的每条消息)。像这样:
tickets
table:
id
created_at
messages
table:
id
created_at
ticket_id
text
source (could be either 'company' or 'client')
我想制作一个 SQL 查询,该查询将生成票证消息,其中每一行都涉及一条 'company' 消息以及自上次 'client' 消息以来的时间延迟。 “时间延迟”是指:
created_at
来自 'company' 消息减去 created_at
来自之前的 'client' 消息
请注意,可以连续发送多个 'company' 或 'client' 条消息。
因此,如果工单(ID 为 4528)有这些消息(按时间顺序):
- 'client' message (id 1)
- 'company' message (id 2)
- 'client' message (id 3)
- 'company' message (id 4)
- 'company' message (id 5)
我希望 SQL 查询产生如下内容:
ticket id | message id | Time diff since previous 'client' message |
---|---|---|
4528 | 2 | time diff between 2 and 1 |
4528 | 4 | time diff between 4 and 3 |
4528 | 5 | time diff between 5 and 3 |
感谢任何帮助。
这是一个例子。 Fiddle
只有 join
company
行具有适用的 client
行具有先前的 created_at
值。然后按相反的时间顺序为每个 company
的这些 client
行分配一个 row_number
。选择 n = 1
以获得每个 company
行的最近前 client
行。
我们可以在 PARTITION BY
子句中添加 ticket_id
来处理多张工单。
SQL:
WITH cte1 (id, ticket_id, text, ts, client_id, ts2, n, dt) AS (
SELECT m1.id, m1.ticket_id, m1.text, m1.created_at
, m2.id AS last_client_id, m2.created_at
, ROW_NUMBER() OVER (PARTITION BY m1.id, m1.ticket_id ORDER BY m2.id DESC) AS n
, m1.created_at - m2.created_at AS dt
FROM messages AS m1
LEFT JOIN messages AS m2
ON m1.ticket_id = m2.ticket_id
AND m2.source = 'client'
AND m2.created_at < m1.created_at
WHERE m1.source = 'company'
)
SELECT * FROM cte1 WHERE n = 1
;
我没有注意到原始问题上的 MySQL
标签,只注意到 postgresql
标签。 SQL两者的结构基本相同,只是在时差计算上稍作调整。
这也是 MariaDB/MySQL 的最新版本 (Fiddle):
WITH cte1 (id, ticket_id, text, ts, client_id, ts2, n, dt) AS (
SELECT m1.id, m1.ticket_id, m1.text, m1.created_at
, m2.id AS last_client_id, m2.created_at
, ROW_NUMBER() OVER (PARTITION BY m1.id, m1.ticket_id ORDER BY m2.id DESC) AS n
, ABS(timestampdiff(minute, m1.created_at, m2.created_at)) AS dt
FROM messages AS m1
LEFT JOIN messages AS m2
ON m1.ticket_id = m2.ticket_id
AND m2.source = 'client'
AND m2.id < m1.id
WHERE m1.source = 'company'
)
SELECT * FROM cte1 WHERE n = 1
;
旧版本的 MySQL 或 Maria 将不支持 WITH clause
或 Window Function
。还是可以的。
设置:
CREATE TABLE messages (
id int
, created_at timestamp
, ticket_id int
, text varchar(30)
, source varchar(20)
);
INSERT INTO messages (id, ticket_id, source, text, created_at) VALUES
(1, 1234, 'client' , 'message 01', current_timestamp + INTERVAL '+1 HOUR')
, (2, 1234, 'company', 'message 02', current_timestamp + INTERVAL '+2 HOUR')
, (3, 1234, 'client' , 'message 03', current_timestamp + INTERVAL '+3 HOUR')
, (4, 1234, 'company', 'message 04', current_timestamp + INTERVAL '+4 HOUR')
, (5, 1234, 'company', 'message 05', current_timestamp + INTERVAL '+5 HOUR')
;
MySQL/MariaDB 的 INTERVAL 语法略有不同:
INSERT INTO messages (id, ticket_id, source, text, created_at) VALUES
(1, 1234, 'client' , 'message 01', current_timestamp + INTERVAL 1 HOUR)
, (2, 1234, 'company', 'message 02', current_timestamp + INTERVAL 2 HOUR)
, (3, 1234, 'client' , 'message 03', current_timestamp + INTERVAL 3 HOUR)
, (4, 1234, 'company', 'message 04', current_timestamp + INTERVAL 4 HOUR)
, (5, 1234, 'company', 'message 05', current_timestamp + INTERVAL 5 HOUR)
;