通过同一表SQL减去组上的两列

时间:2018-08-27 01:19:19

标签: sql postgresql

我有这张桌子

create table events 
(
      event_type integer not null,
      value integer not null,
      time timestamp not null,
      unique(event_type, time)
);

我想编写一个SQL查询,对于每个已多次注册的SQL查询,返回的是最新的(即,最新的)与第二个最新的之间的差额。该表应按(升序)排序。

样本数据为:

 event_type   | value      | time
 -------------+------------+--------------------
   2          |  5         | 2015-05-09 12:42:00
   4          | -42        | 2015-05-09 13:19:57
   2          |  2         | 2015-05-09 14:48:30
   2          |  7         | 2015-05-09 12:54:39
   3          | 16         | 2015-05-09 13:19:57
   3          | 20         | 2015-05-09 15:01:09

输出应为

   event_type | value
  ------------+-----------
   2          | -5
   3          | 4

到目前为止,我尝试这样做

SELECT event_type  
FROM events 
GROUP BY event_type
HAVING COUNT(event_type) > 1 
ORDER BY event_type

我找不到第二种方法为我提到的第二列获取正确的值。我正在使用PostgreSQL 9.4

2 个答案:

答案 0 :(得分:1)

您可以使用ANSI / ISO标准窗口功能执行此操作:

select event_type,
       sum(case when seqnum = 1 then value
                when seqnum = 2 then - value
           end) as diff_latest
from (select e.*,
             row_number() over (partition by event_type order by time desc) as seqnum
      from events e
     ) e
where seqnum in (1, 2)
group by event_type
having count(*) = 2;

Here是一个SQL提琴。

答案 1 :(得分:1)

使用lead的一种方法,该方法根据指定的顺序获取给定列的下一个值。给定event_type的倒数第二行将具有最新值,在这种情况下可用于减去。 (运行内部查询以了解如何分配next_val

select event_type,next_val-value as diff
from (select t.*
      ,lead(value) over(partition by event_type order by time) as next_val, 
      ,row_number() over(partition by event_type order by time desc) as rnum
      from tbl t
     ) t 
where next_val is not null and rnum=2

还有一个DISTINCT ONlead的选项。

select distinct on (event_type) event_type,next_val-value as diff
from (select t.*,lead(value) over(partition by event_type order by time) as next_val 
      from events t
     ) t 
where next_val is not null 
order by event_type,time desc