SQL - 按唯一 ID 分组的 2 个条目之间的时间差

SQL - Time difference between 2 entries grouped by unique ID

我有一个 table,其中包含针对不同 ID 的不同操作的多个时间戳条目(我们称它们为操作 'A' 和 'B'),我想计算它们之间的差异每个 ID 在元数据库中使用 SQL。

为了让事情变得更复杂,我需要只过滤包含两种动作类型的ID,有时会有重复的动作名称并不总是相同的顺序,所以我需要找到动作的MIN 'A' 并希望获得 Action 'B'.

的下一个最高时间戳

例如,这里有一个数据集:

ID   | Action | Timestamp
----------------------------------------------
01   | A      | Thursday, June 6, 2019 6:25 AM <-First valid action for 'A' for ID 01
01   | B      | Thursday, June 6, 2019 6:30 AM <-First valid action for 'B' for ID 01
01   | A      | Thursday, June 6, 2019 6:35 AM
01   | B      | Thursday, June 6, 2019 6:40 AM
01   | A      | Thursday, June 6, 2019 6:45 AM
03   | B      | Monday, July 1, 2019 8:25 AM   <-SKIP, due to no Action 'A' present for ID 03
03   | B      | Monday, July 1, 2019 8:30 AM
10   | B      | Tuesday, July 2, 2019 9:40 AM
10   | A      | Tuesday, July 2, 2019 9:45 AM  <-First valid action for 'A' for ID 10
10   | A      | Tuesday, July 2, 2019 9:50 AM
10   | B      | Tuesday, July 2, 2019 9:55 AM  <-First valid action for 'B' for ID 10

我想要的结果是仅查看同时具有操作 'A' 和 'B' 的 ID(提示:如果存在操作 'A',将始终有一个操作'B',但有时只有一个动作 'B'),并找到与第一个动作 'A'(在最早的动作 'B' 之后出现)的时间戳差异,以及下一个最高操作 'B'.

想要的结果:

ID   | Difference
-----------------
01   | 5 min
10   | 10 min

总结一下:

• 我如何识别操作 'B' 后操作 'A' 的第一个时间戳?

• 如何计算该操作 'A' 与下一个最高操作 'B' 的差异,以便在每个不同 ID 的结果中显示在同一行中?

• 如何仅查看同时存在这两种操作的 ID?

我不知道你用的是哪种 SQL 方言,所以我试着写了一个非常接近标准 SQL 的查询(例如 SQL:2003), but using Postgres 8.4. For the character representation of date values, I used the format defined in ISO 8601.

create table T (
  ID char(2),
  Action char(1),
  "Timestamp" timestamp
);

insert into T values
  ('01', 'A', '2019-06-06T06:25'),
  ('01', 'B', '2019-06-06T06:30'),
  ('01', 'A', '2019-06-06T06:35'),
  ('01', 'B', '2019-06-06T06:40'),
  ('01', 'A', '2019-06-06T06:45'),
  ('03', 'B', '2019-07-01T08:25'),
  ('03', 'B', '2019-07-01T08:30'),
  ('10', 'B', '2019-07-02T09:40'),
  ('10', 'A', '2019-07-02T09:45'),
  ('10', 'A', '2019-07-02T09:50'),
  ('10', 'B', '2019-07-02T09:55');

select
  a.ID, extract(minute from (min(b."Timestamp") - a.min_ts)) as Difference
from (select
        t.ID, min(t."Timestamp") as min_ts
      from T as t
      where t.Action = 'A'
      group by t.ID, t.Action) as a
inner join T as b
  on a.ID = b.ID and b.Action = 'B' and a.min_ts < b."Timestamp"
group by a.ID, a.min_ts;

输出:

| id | difference |
+----+------------+
| 10 |         10 |
| 01 |          5 |

使用 SQL Fiddle 在线测试。