从旅行信息获取当前国家

时间:2016-02-08 00:00:05

标签: sql sql-server sql-server-2008 tsql

我有一个简单的表(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_datearrival_date定义旅行者何时离开country_from,以及何时他将在country_to ...实际上是time spend in flight

(我同意,这张桌子很糟糕,并且有很多正常化的问题,但我无法管理它,我们拥有的东西)

我需要写一个查询,它将返回旅行者姓名,以及旅行者所在国家/地区(如果许多国家是第一个国家/地区)在给定时间段内...

例如对于时间段2016-03-01 - 2016-04-02查询应该返回

Test1 Italy
Test2 USA

请建议获得该结果的最佳方式,我已尝试将表格本身与少数变体联系起来,但总是遇到未涵盖的极端情况

1 个答案:

答案 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;