计算表中每一天的最大时间间隔

时间:2019-05-11 15:33:58

标签: sql postgresql

我在PostgreSQL数据库中有一个表,如下所示:

PageLinkTagHelper

我想创建一个函数来计算每天从9:00到20:00的最大时间间隔(以分钟为单位),并获得一个新表。例如:

id |    date    | time_begin | time_end
1  | 2019-03-05 | 10:00:00   | 11:00:00
2  | 2019-03-05 | 13:00:00   | 14:30:00
3  | 2019-03-05 | 14:20:00   | 15:00:00
4  | 2019-03-05 | 17:00:00   | 19:00:00
5  | 2019-03-06 | 09:00:00   | 11:00:00
6  | 2019-03-06 | 10:50:00   | 13:00:00
7  | 2019-03-07 | 10:00:00   | 11:00:00
8  | 2019-03-14 | 12:00:00   | 15:30:00
9  | 2019-03-14 | 16:00:00   | 17:00:00
10 | 2019-03-15 | 18:00:00   | 19:00:00
11 | 2019-03-25 | 09:00:00   | 11:00:00
12 | 2019-03-25 | 11:00:00   | 13:00:00
13 | 2019-03-25 | 13:00:00   | 15:00:00
14 | 2019-03-25 | 15:00:00   | 20:00:00
15 | 2019-03-26 | 09:00:00   | 20:00:00
16 | 2019-03-30 | 09:00:00   | 12:00:00
17 | 2019-03-30 | 12:00:00   | 16:00:00
18 | 2019-03-30 | 16:00:00   | 20:00:00

该怎么做?有什么想法吗?

3 个答案:

答案 0 :(得分:0)

尝试一下-

SELECT 
Date, 
MAX(DATEDIFF(mi, time_begin , time_end ) )
FROM your_table
GROUP BY Date

答案 1 :(得分:0)

这是您想要的吗?

select date, max(time_end - time_begin)
from t
group by date
order by date;

如果您希望以分钟为单位:

select date,
       extract(epoch from max(time_end - time_begin)) / 60
from t
group by date
order by date;

尚不清楚您是否需要关注自己的界限;所有值似乎都在范围内。

答案 2 :(得分:0)

首先,我想您通过要求“最大间隔”来抛弃所有人,而没有更多的解释。数据集中的每一行都定义了一个间隔,因此您最终得到了显示该间隔的响应。

如果我理解正确,那么您正在寻找的是:“每天的最大时间段,介于上午9点至晚上8点之间,并且不在数据集中的时间段内”。那就是我会努力为您准备的。

事实证明,这比人们以为您在问的问题简单得多:)

我们想在不同的行之间进行一些计算。在SQL中,这样做的方法是使用window functions。在这种情况下,我们要使用leadlag。我们要按日期划分。

在这种情况下,前一行的time_end将表示为:

lag(time_end, 1)
  OVER (PARTITION BY date ORDER BY time_begin)

如果愿意,您也可以按ID排序,但是由于我们正在比较时间,因此使用时间进行排序似乎是合理的。同样,下一个行的time_begin如下:

lead(time_begin, 1)
  OVER (PARTITION BY date ORDER BY time_begin)

将它们与一点日期数学加在一起,整个查询看起来像:

SELECT date,
  time_begin - lag(time_end, 1)
                OVER (PARTITION BY date ORDER BY time_begin),
  lead(time_begin, 1) OVER (PARTITION BY date ORDER BY time_begin)
    - time_end
FROM your_table
ORDER BY date;

结果类似于:

    date    | ?column?  | ?column?  
------------+-----------+-----------
 2019-03-05 |           | 02:00:00
 2019-03-05 | 02:00:00  | -00:10:00
 2019-03-05 | -00:10:00 | 02:00:00
 2019-03-05 | 02:00:00  | 
...

这使我们相距甚远。不过,值得注意的是,我们错过了上午9点到第一个time_begin之间的时间间隔。与上一个time_end和晚上8点相同-它们只是显示为null。幸运的是,laglead带有一个额外的选项参数作为默认值:

SELECT date,
  time_begin - lag(time_end, 1, '09:00:00')
                OVER (PARTITION BY date ORDER BY time_begin),
  lead(time_begin, 1, '20:00:00') OVER (PARTITION BY date ORDER BY time_begin)
    - time_end
FROM your_table
ORDER BY date;

结果:

    date    | ?column?  | ?column?  
------------+-----------+-----------
 2019-03-05 | 01:00:00  | 02:00:00
 2019-03-05 | 02:00:00  | -00:10:00
 2019-03-05 | -00:10:00 | 02:00:00
 2019-03-05 | 02:00:00  | 01:00:00
...

好的,现在我们到了某个地方。但是我们需要汇总一下。让我们使用common table expressions,因为我们已经有了一个有效的查询。我还将为我们的间隔列添加一些列别名:

WITH date_intervals as (
 SELECT date,
    time_begin - lag(time_end, 1, '09:00:00')
                  OVER (PARTITION BY date ORDER BY time_begin) AS interval1,
    lead(time_begin, 1, '20:00:00') OVER (PARTITION BY date ORDER BY time_begin)
      - time_end AS interval2
  FROM your_table
  ORDER BY date)
SELECT date, max(interval1), max(interval2)
FROM date_intervals
GROUP BY date
ORDER BY date;

现在,让我们使用Gordon Linoff's的想法转换为分钟,然后使用greatest函数获得所需的内容:

WITH date_intervals as (
 SELECT date,
    time_begin - lag(time_end, 1, '09:00:00')
                  OVER (PARTITION BY date ORDER BY time_begin) AS interval1,
    lead(time_begin, 1, '20:00:00') OVER (PARTITION BY date ORDER BY time_begin)
      - time_end AS interval2
  FROM your_table
  ORDER BY date)
SELECT date,
  greatest(
    extract(epoch from max(interval1)) / 60,
    extract(epoch from max(interval2)) / 60)
FROM date_intervals
GROUP BY date
ORDER BY date;

就在那里。很复杂,但是一步一步就能实现。