PostgreSQL时间范围持续时间系列,默认结束时为null

时间:2013-09-18 03:58:33

标签: sql postgresql

我需要能够使用默认的end_datetime计算两个时间戳之间的持续时间(以秒为单位)作为一个时间序列的聚合,如果它为空。

想象一下,当你进出时,你会有一张像打卡的东西: username,start_datetime,end_datetime

我想要的是生成的最后N分钟的时间序列,其中所有用户的持续时间在该时间范围内重叠。所以它将是SUM(end_datetime - start_datetime),如果它是null,你将COALESCE默认的end_datetime。

所以我认为我需要的基本部分是:

生成时间间隔:

select TIMESTAMP '2013-01-01 12:01:00' - (interval '1' minute * generate_series(0,5)) as timestamps;

COALESCE是默认的end_datetime

COALESCE(end_datetime, NOW())

计算开始日期和结束日期之间的秒差

因此,如果一个用户在11:56:50登录并且现在是12:01:40,我们应该得到一个像这样的表:

     timestamps          duration
-------------------------------------
 2013-01-01 12:01:00        40
 2013-01-01 12:00:00        60
 2013-01-01 11:59:00        60
 2013-01-01 11:58:00        60
 2013-01-01 11:57:00        60
 2013-01-01 11:56:00        10

1 个答案:

答案 0 :(得分:2)

with t as (select '2013-01-01 11:56:50'::timestamp startt, '2013-01-01 12:01:40'::timestamp endt)

select
   timestamps,
   extract(epoch from 
   case 
      when timestamps=date_trunc('minute',startt) then date_trunc('minute',startt) + interval '1 minute' - startt
      when timestamps =date_trunc('minute',endt) then endt- date_trunc('minute',endt)
      else interval '60 seconds' end) as durations
from
   (select generate_series(date_trunc('minute',startt),date_trunc('minute',endt),'1 minute') timestamps, * from t) a
order by
   timestamps desc;

2013-01-01 12:01:00;40
2013-01-01 12:00:00;60
2013-01-01 11:59:00;60
2013-01-01 11:58:00;60
2013-01-01 11:57:00;60
2013-01-01 11:56:00;10

如果您有多个包含开始和结束时间戳的行,则以下内容将起作用:

select
   id,
   timestamps,
   extract(epoch from 
   case 
      when timestamps=date_trunc('minute',startt) then date_trunc('minute',startt) + interval '1 minute' - startt
      when timestamps =date_trunc('minute',endt) then endt- date_trunc('minute',endt)
      else interval '60 seconds' end) as durations
from
   (
      select 
      id,
      generate_series(date_trunc('minute',startt) ,
                      coalesce(date_trunc('minute',endt),date_trunc('minute',Now())),'1 minute') as timestamps,
      startt, endt
   from test
   ) a
order by
   id, timestamps desc

SQLFiddle