计算同一列中两个日期之间的日期
Posted
技术标签:
【中文标题】计算同一列中两个日期之间的日期【英文标题】:Counting dates that fall between two dates in the same column 【发布时间】:2013-08-02 07:20:21 【问题描述】:我有两个表,对于表 1 中的每个 ID 和级别组合,我需要在表 1 中的级别的连续时间之间获取匹配 ID 出现在表 2 中的次数。
因此,例如,对于 table1 中的 ID = 1 和 Level=1,来自 table2 的两个 ID = 1 的时间条目落在 table1 中 Level=1 和 Level=2 的时间之间,因此结果表中的结果将为 2 .
table1:
ID Level Time
1 1 6/7/13 7:03
1 2 6/9/13 7:05
1 3 6/12/13 12:02
1 4 6/17/13 5:01
2 1 6/18/13 8:38
2 3 6/20/13 9:38
2 4 6/23/13 10:38
2 5 6/28/13 1:38
table2:
ID Time
1 6/7/13 11:51
1 6/7/13 14:15
1 6/9/13 16:39
1 6/9/13 19:03
2 6/20/13 11:02
2 6/20/13 15:50
结果是
ID Level Count
1 1 2
1 2 2
1 3 0
1 4 0
2 1 0
2 3 2
2 4 0
2 5 0
【问题讨论】:
您是否尝试过lag
或lead
函数来获取Time
的下一个/上一个值?
【参考方案1】:
select transformed_tab1.id, transformed_tab1.level, count(tab2.id)
from
(select tab1.id, tab1.level, tm, lead(tm) over (partition by id order by tm) as next_tm
from
(
select 1 as id, 1 as level, '2013-06-07 07:03'::timestamp as tm union
select 1 as id, 2 as level, '2013-06-09 07:05 '::timestamp as tm union
select 1 as id, 3 as level, '2013-06-12 12:02'::timestamp as tm union
select 1 as id, 4 as level, '2013-06-17 05:01'::timestamp as tm union
select 2 as id, 1 as level, '2013-06-18 08:38'::timestamp as tm union
select 2 as id, 3 as level, '2013-06-20 09:38'::timestamp as tm union
select 2 as id, 4 as level, '2013-06-23 10:38'::timestamp as tm union
select 2 as id, 5 as level, '2013-06-28 01:38'::timestamp as tm) tab1
) transformed_tab1
left join
(select 1 as id, '2013-06-07 11:51'::timestamp as tm union
select 1 as id, '2013-06-07 14:15'::timestamp as tm union
select 1 as id, '2013-06-09 16:39'::timestamp as tm union
select 1 as id, '2013-06-09 19:03'::timestamp as tm union
select 2 as id, '2013-06-20 11:02'::timestamp as tm union
select 2 as id, '2013-06-20 15:50'::timestamp as tm) tab2
on transformed_tab1.id=tab2.id and tab2.tm between transformed_tab1.tm and transformed_tab1.next_tm
group by transformed_tab1.id, transformed_tab1.level
order by transformed_tab1.id, transformed_tab1.level
;
【讨论】:
【参考方案2】:SQL Fiddle
select t1.id, level, count(t2.id)
from
(
select id, level,
tsrange(
"time",
lead("time", 1, 'infinity') over(
partition by id order by level
),
'[)'
) as time_range
from t1
) t1
left join
t2 on t1.id = t2.id and t1.time_range @> t2."time"
group by t1.id, level
order by t1.id, level
解决方案开始使用lead
窗口函数创建一系列时间戳。注意tsrange
构造函数的[)
参数。这意味着包括下限并排除上限。
然后它使用@>
范围运算符连接两个表。这意味着范围包括元素。
left join
t1 必须有零计数。
【讨论】:
我相信应该可以正常工作,但刚刚发现我们使用 Amazon Redsfhit 并且不支持某些功能。对于前导函数,我收到错误消息“窗口函数前导不支持默认参数”并且 tsrange 函数不存在。我会尝试看看是否有解决方法。谢谢!以上是关于计算同一列中两个日期之间的日期的主要内容,如果未能解决你的问题,请参考以下文章