在sqlserver中获取行程期限

时间:2017-07-13 12:04:57

标签: sql sql-server

我有一个GPS应用程序,可以将数据保存到下表:

CREATE TABLE [dbo].[T_Tracking]
(
    [id]          [int] IDENTITY(1,1) NOT NULL,
    [IMEI]        [nvarchar](50) NULL,
    [TrackTime]   [datetime] NULL,
    [Longitude]   [nvarchar](50) NULL,
    [Lattitude]   [nvarchar](50) NULL,
    [speed]       [float] NULL,
    [CarID]       [int] NULL,
    [Country]     [nvarchar](50) NULL,
    [City]        [nvarchar](50) NULL,
    [Area]        [nvarchar](50) NULL,
    [Street]      [nvarchar](50) NULL,
    [FullAddress] [nvarchar](150) NULL,
    [Distance]    [float] NULL
    -- ...
)

我想做一个旅行查询拉回开始时间&速度,结束时间和速度。

这是我的疑问:

SELECT id
, IMEI
, TrackTime as StartTime
, speed as StartSpeed
, CarID
, FullAddress
, (
    SELECT TOP (1) TrackTime AS Expr1
    FROM T_Tracking AS E2
    WHERE (CarID = E1.CarID) 
    AND (id > E1.id) 
    AND (speed <5)
    ORDER BY id desc
) AS StopTime 
, (
    SELECT TOP (1) speed AS Expr1
    FROM T_Tracking AS E2
    WHERE (CarID = E1.CarID) 
    AND (id > E1.id) 
    AND (speed <5)      
    ORDER BY id desc
) AS EndSpeed 
FROM T_Tracking AS E1 
WHERE (speed > 5) 
order by id desc

它工作正常,但是如果这次旅行应该停车15分钟(即因为汽车可能停在交通中一分钟或者2分钟,那么我们不希望计算作为旅行的结束) 我该如何添加这个逻辑?

此外,我需要将距离场相加以获得行程总距离。

样本表数据:

enter image description here

期望的结果是:

enter image description here

注意:

  1. GPS每30秒保存一次记录
  2. 汽车可能会停在交通中,所以要确定行程已经结束,必须停车15分钟
  3. 并不总是speed=0它将是speed<5(设备准确度/容差)
  4. 距离是当前点与前一点之间的距离(30秒内的距离)

2 个答案:

答案 0 :(得分:0)

这是演示如何获得停止的演示。为简单起见,我使用所有INT来表示时间和速度,查询可以很容易地适应DATETIME数据类型。如果持续时间> 1,则记录停止。 4。

SELECT CarID, stopped, grp 
   , min(TrackTime) stopStartTime
   , max(TrackTime) + 1 - min(TrackTime) stopDuration
FROM (
    SELECT id, TrackTime, CarID, stopped
      , row_number() over (partition by CarID order by TrackTime) - row_number() over (partition by CarID, stopped order by TrackTime)  grp
    FROM (
        SELECT id, TrackTime, CarID, CASE WHEN speed > 5 THEN 0 ELSE 1 END stopped
        FROM (
            -- Demo data
            VALUES 
             (0,0,10, 2)
            ,(1,1,10, 8)
            ,(2,2,10, 8)
            ,(3,3,10, 4)
            ,(4,4,10, 4)
            ,(5,5,10, 4)
            ,(6,6,10, 4)
            ,(7,7,10, 4)
            ,(8,8,10, 4)
            ,(9,9,10, 8)
        ) T_Tracking (id, TrackTime, CarID, speed)
    ) g
 ) t
 GROUP BY CarID, stopped, grp
 HAVING max(TrackTime) + 1 - min(TrackTime) > 4
 ORDER BY min(TrackTime)

答案 1 :(得分:0)

试试这个(未经测试):

select JourneyBounds.id
, JourneyBounds.IMEI
, JourneyBounds.TrackTime as StartTime
, JourneyBounds.speed as StartSpeed
, JourneyBounds.CarID
, JourneyBounds.FullAddress
, max(journey.TrackTime) StopTime
, max(case when journey.id = JourneyBounds.EndOfJourneyId then journey.speed else null end) EndSpeed
, JourneyBounds.Distance + sum(journey.Distance) TotalDistance 
from (
    select *
    , (
        select min(id) 
        from T_Tracking EndOfJourney
        where EndOfJourney.Id > StartOfJourney.Id
        and EndOfJourney.CarId = StartOfJourney.CarId
        and EndOfJourney.speed < 5
        --edit; car must have been stopped for 15 mins; so we need to check that the records after this stop confirm that (i.e. that the car does not move in that time)
        and not exists (
            select top 1 1
            from T_Tracking WaitFifteenMins
            where WaitFifteenMins.Id > EndOfJourney.Id
            and WaitFifteenMins.TrackTime <= DateAdd(minute, 15, EndOfJourney.TrackTime)
            and WaitFifteenMins.speed >= 5
        ) 
        --end of edit
    ) EndOfJourneyId 
    from T_Tracking StartOfJourney
    where StartOfJourney.speed < 5
) JourneyBounds
inner join T_Tracking journey
on journey.CarId = JourneyBounds.CarId 
and journey.id > JourneyBounds.Id 
and journey.id <= JourneyBounds.EndOfJourneyId
group by JourneyBounds.id
, JourneyBounds.IMEI
, JourneyBounds.TrackTime 
, JourneyBounds.speed
, JourneyBounds.CarID
, JourneyBounds.FullAddress
, JourneyBounds.Distance 
having count(1) > 1

JourneyBounds子查询获取speed < 5的所有记录(即任何潜在旅程的起始记录)。此外,它会在该开始后拉回第一站的id(即第一个具有更大id且速度小于5的记录)。

然后它会在内部联接中拉回在开始时间之后到达同一辆车的所有记录,直到&amp;包括此旅程的最终记录。然后,我们通过将这段旅程中记录的所有距离相加来计算距离。

最后的having count(1) > 1只是说如果汽车的开始记录后立即停止,我们可以假设它没有移动/没有旅程。据推测,我们不希望在结果中出现这些非旅程。