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

时间:2019-07-02 17:30:38

标签: sql metabase

我有一个表,其中有多个时间戳记条目用于不同的ID(对于不同的ID,我们将其称为Action“ A”和“ B”),我想使用Metabase中的SQL计算每个ID的差异。 >

为了使事情变得更复杂,我只需要过滤包含两种动作类型的ID,有时重复的动作名称并不总是相同的顺序,因此我需要找到动作“ A”的MIN并希望获得动作“ 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

所以总结一下:

•如何确定动作“ A”之后的动作“ B”的第一个时间戳?

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

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

1 个答案:

答案 0 :(得分:1)

我不知道您使用哪种SQL方言,因此我尝试编写一个非常接近标准SQL(例如SQL:2003)的查询,但是使用了Postgres 8.4。对于日期值的字符表示,我使用了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在线进行测试。