按时间顺序获取每个州的第一站和最后一站

时间:2016-02-19 20:19:19

标签: sql tsql

我有一张桌子可以跟踪每个州的车辆停靠情况。例如,车辆可以在一个状态中进行多次停止,进入另一个状态,然后在给定的一天中返回到相同的状态。以下是我的意思的样本:

VehicleID | State | LocationDate            | EventType
-------------------------------------------------------
1         | KY    | 2013-02-10 05:09:00.000 | Delivery
1         | KY    | 2013-02-10 05:45:00.000 | Delivery
1         | KY    | 2013-02-10 06:10:00.000 | Gas
1         | IN    | 2013-02-10 08:33:00.000 | Delivery
1         | KY    | 2013-02-10 10:13:00.000 | Delivery

我希望按时间顺序获得每个州的第一次和最后一次停留时间。如果列表中下一个状态只有一行,则再次列出该行。例如,我正在寻找以下内容:

VehicleID | State | LocationDate            | FirstOrLast
---------------------------------------------------------
1         | KY    | 2013-02-10 05:09:00.000 | First
1         | KY    | 2013-02-10 06:10:00.000 | Last
1         | IN    | 2013-02-10 08:33:00.000 | First
1         | IN    | 2013-02-10 08:33:00.000 | Last
1         | KY    | 2013-02-10 10:13:00.000 | First
1         | KY    | 2013-02-10 10:13:00.000 | Last

1 个答案:

答案 0 :(得分:0)

基本上,您要为连续状态添加分组标识符。您可以使用行号的差异来执行此操作。这是识别连续行组的一种聪明方法。

然后,根据该信息,您可以使用row_number()获取所需信息。因为您希望重复行,所以我建议使用union all方法:

with g as (
      select t.*,
             row_number() over (partition by vehicleId, grp, state order by LocationDate) as seqnum_asc,
             row_number() over (partition by vehicleId, grp, state order by LocationDate desc) as seqnum_desc
      from (select t.*,
                   (row_number() over (partition by VehicleID order by LocationDate) -
                    row_number() over (partition by VehicleID, State order by LocationDate)
                   ) as grp
            from t
           ) t
     )
select g.*, 'First' as FirstOrLast
from g
where seqnum_asc = 1
union all
select g.*, 'Last' as FirstOrLast
from g
where seqnum_desc = 1;