我有一个简单的表(TRIP),它存储旅行信息,如下所示
trip_id traveler country_from country_to departure_date arrival_date
1 Test1 Germany Italy 2016-01-01 2016-01-02
1 Test1 Italy France 2016-04-01 2016-04-02
1 Test1 France Italy 2016-08-28 2016-08-28
1 Test1 Italy Germany 2016-08-30 2016-10-31
2 Test2 France USA 2016-01-28 2016-02-28
2 Test2 USA France 2016-08-30 2016-10-31
实际上这意味着
Test1 travels: Germany -> Italy -> France -> Italy -> Germany
Test2 travels: from France -> USA -> France
departure_date
和arrival_date
定义旅行者何时离开country_from
,以及何时他将在country_to
...实际上是time spend in flight
(我同意,这张桌子很糟糕,并且有很多正常化的问题,但我无法管理它,我们拥有的东西)
我需要写一个查询,它将返回旅行者姓名,以及旅行者所在国家/地区(如果许多国家是第一个国家/地区)在给定时间段内...
例如对于时间段2016-03-01 - 2016-04-02查询应该返回
Test1 Italy
Test2 USA
请建议获得该结果的最佳方式,我已尝试将表格本身与少数变体联系起来,但总是遇到未涵盖的极端情况
答案 0 :(得分:2)
您需要在一行中为每个国家/地区的行程的开始和结束。在SQL Server 2012+中,您可以使用lead()
来实现此目的。查询的其余部分只是处理重叠的时间段:
select t.*
from (select t.country_to as country, t.arrival_date,
lead(t.departure_date) over (partition by t.traveler order by arrival_date) as departure_date
from trips t
where t.traveler = @traveler
) t
where @date1 <= t.departure_date and
@date2 >= t.arrival_date;
编辑:
您可以使用outer apply
在早期版本中执行相同的操作:
select t.*
from (select t.country_to as country, t.arrival_date,
t2.departure_date
from trips t outer apply
(select top 1 t2.*
from trips t2
where t2.traveler = t.traveler and
t2.arrival_date > t.arrival_date
order by t2.arrival_date
) t2
where t.traveler = @traveler
) t
where @date1 <= t.departure_date and
@date2 >= t.arrival_date;