我在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
该怎么做?有什么想法吗?
答案 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。在这种情况下,我们要使用lead
和lag
。我们要按日期划分。
在这种情况下,前一行的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。幸运的是,lag
和lead
带有一个额外的选项参数作为默认值:
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;
就在那里。很复杂,但是一步一步就能实现。