SQL-根据来自不同行的同一列获取日期差异

时间:2019-04-08 11:44:12

标签: sql postgresql

我有一个表,其中将所有更新存储在表单字段中。我正在尝试建立一个查询,以计算每次更新之间经过了多少时间。

这是我的桌子的一个例子:

ticket,last_update,status
12345,2019-03-29 13:54:55.000000,canceled
12345,2019-03-29 12:46:20.000000,analysis
12345,2019-03-28 18:30:55.000000,canceled
12345,2019-03-28 09:31:20.000000,analysis

我想检查分析与其他状态之间的状态变化差异时间(每个分析都有一个后续状态)。

示例输出:

First analysis: differente between analysis 2019-03-28 09:31:20.000000 and 2019-03-28 18:30:55.000000 canceled
First analysis: differente between analysis 2019-03-29 12:46:20.000000 and 2019-03-29 13:54:55.000000 canceled

是否可以编写一条SQL语句返回此数据?我坚持这句话:

select ticket, last_update, status from history as h
where h.ticket = 12345
  and h.field = 'custom_field_a';

我想避免在后端编写一些代码来执行它。

使用PARTITION BY对其进行了尝试:

select ticket,
       last_update - lag(last_update) over (partition by ticket order by last_update) as difference
from history as h
where h.ticket = 12345
  and h.field = 'custom_field_a'
group by ticket, last_update;

它应该返回2行,其中包含与分析的差异->已取消,分析->已取消,但我有4行。

4 个答案:

答案 0 :(得分:1)

您可以使用LAG功能,该功能从上一行获取数据。下面的查询应该能够计算出差异:

 SELECT last_update - lag(last_update) over (order by last_update) as difference
        FROM history AS h
        where h.ticket = 12345
              and h.field = 'custom_field_a';

/ A

答案 1 :(得分:0)

您可以执行以下操作:

select ticket,
       max(last_update) filter (where status = 'created') as created_ts,
       max(last_update) filter (where status = 'cancelled') as cancelled_ts,
       max(last_update) filter (where status = 'analysis') as analysis_ts,
from history as h
where h.ticket = 12345 and
      h.field = 'custom_field_a'
group by ticket;

我不确定您要如何表达差异,但是您可以减去相关值。

答案 2 :(得分:0)

您可以加入相关行,如下所示:

  select created.ticket
       , created.last_update as created_ts
       , analysis.last_update as analysis_ts
       , canceled.last_update as canceled_ts
    from history as created
    left join history as analysis
      on created.ticket = analysis.ticket
     and created.field = analysis.field
     and analysis.status = 'analysis'
    left join history as canceled
      on created.ticket = canceled.ticket
     and created.field = canceled.field
     and canceled.status = 'canceled'
   where created.ticket = 12345
     and created.field = 'custom_field_a'
     and created.status = 'created'

不确定field是如何发挥作用的,它可能也是所有联接的联接条件。如果每种状态只有一个条目,这将起作用,否则,您将获得重复的行,并且可能需要其他策略。

答案 3 :(得分:0)

您将要使用lag()窗口函数获取两者之间的时间差

https://www.postgresql.org/docs/current/functions-window.html

编辑您可能想使用CTE首先过滤查询以获得所需结果。

with history_set as(
    select
        ticket,
        lag(last_update)
            over (partition by ticket order by last_update) as prev_update,
        last_update,
        last_update - lag(last_update)
        over (partition by ticket order by last_update) as time_diff,
        status
     from history as h
    where h.ticket = 12345
      and h.field = 'custom_field_a'
    order by last_update
)
select
    ticket,
    prev_update,
    last_update,
    time_diff,
    status
from history_set
where status <> 'analysis'