SQL:执行计算并确保每个id的第一个记录是空值

时间:2014-03-11 02:25:13

标签: sql sql-server gps

我正在使用SQL Server 2012.我有一个非常大的数据库,包含超过4000万条用于邮件传递的GPS轨道记录。我可以使用以下查询计算每条记录的时差:

UPDATE a SET SecSince=
  DATEDIFF(SECOND, (SELECT TOP 1 [DateTime]
                 FROM [dbo].[Database]
                 WHERE
                     COMPANY=a.COMPANY
                     AND CarrierID=a.CarrierID
                     AND  [DateTime]< a.[DateTime]
                 ORDER BY [DateTime] DESC)
              , a.[DateTime])
FROM [dbo].[Database] a
WHERE 0 < (SELECT COUNT(*) FROM [dbo].[Database]
           WHERE
               Company=a.Company
               AND CarrierID=a.CarrierID
               AND [DateTime] < a.[DateTime])

结果如下:

Company CarrierID   SecSince    
    A   1           NULL     
    A   1           800    
    A   1           900    
    B   1           NULL       
    B   1           876    
    B   1           904    
    B   2           NULL       
    B   2           122    
    B   2           177    

每个新的carrierid和公司的第一条记录都是NULL值 - 这正是我想要的。

这里我遇到了困难。我想运行相同的查询,但这次我想计算GPS距离。我可以使用以下公式计算Haversine距离:

UPDATE A
set A.[Haversine] = 
6371000* 2 * ASIN ( SQRT (POWER(SIN((A.Latitude - B.Latitude)*pi()/180 / 2),2) + COS(A.Latitude * pi()/180) * COS(B.Latitude *pi()/180) * POWER(SIN((A.Longitude - B.Longitude) *pi()/180 / 2), 2) ) )
from [dbo].[Database] A INNER JOIN [dbo].[Database] B ON B.ID = (A.ID + 1)
WHERE A.[Trip] = A.[Trip]

这在距离计算方面工作正常。除了现在我想要每个新的CarrierID和Company组合记录(或Trip)的第一条记录的NULL值,就像在SecSince计算中一样。

我尝试重新编写SecSince查询,以便运行距离计算,但我似乎无法正确使用语法。我想问题是嵌套的选择顶部1.我希望有人可以告诉我我做错了什么,并帮助我正确的语法。

UPDATE A
set A.[Haversine] = 
6371000* 2 * ASIN ( SQRT (POWER(SIN((A.Latitude - B.Latitude)*pi()/180 / 2),2) + COS(A.Latitude * pi()/180) * COS(B.Latitude *pi()/180) * POWER(SIN((A.Longitude - B.Longitude) *pi()/180 / 2), 2) ) )
(SELECT TOP 1 [DateTime]
        FROM [dbo].[Database]
                 WHERE
                     COMPANY=a.COMPANY
                     AND CarrierID=a.CarrierID
                     AND  [DateTime]< a.[DateTime]
                 ORDER BY [DateTime] DESC)
              , a.[DateTime])
from [dbo].[Emerson] A INNER JOIN [dbo].[Database] B ON B.ID = (A.ID + 1)
WHERE A.[Trip] = A.[Trip]
FROM [dbo].[Database] a
WHERE 0 < (SELECT COUNT(*) FROM [dbo].[Database]
           WHERE
               Company=a.Company
               AND CarrierID=a.CarrierID
               AND [DateTime] < a.[DateTime])

这是我想要的结果:

Trip Company CarrierID Latitude Longitude ID    DateTime           SecSince Haversine DESIRED
    3   7002    1   50.06417    -96.46426   1   15/02/2013 14:40:38 NULL    6.05    NULL
    3   7002    1   50.06421    -96.4643    2   15/02/2013 14:55:37 899     0.00    6.05
    3   7002    1   50.06421    -96.4643    3   15/02/2013 15:08:46 789     16.61   0.00
    4   7003    1   50.06435    -96.46421   4   15/02/2013 15:21:06 NULL    0.00    NULL
    4   7003    1   50.06435    -96.46421   5   15/02/2013 15:22:16 70      0.00    0.00
    4   7003    1   50.06435    -96.46421   6   15/02/2013 15:23:06 50      0.00    0.00
    5   7002    3   50.06435    -96.46421   7   15/02/2013 15:32:51 NULL    0.00    NULL
    5   7002    3   50.06435    -96.46421   8   15/02/2013 15:33:01 10      5.51    0.00
    5   7002    3   50.0644     -96.46421   9   15/02/2013 15:38:30 329     5.51    5.51
    5   7002    3   50.06435    -96.46421   10  15/02/2013 15:45:04 394     0.00    5.51

1 个答案:

答案 0 :(得分:1)

如果您有SQL Server 2012,则应使用酷炫的新功能,例如LAG

with cte as
(
  select 
    id,
    lag([datetime],1) over(partition by trip order by id) as prev_datetime,
    lag([latitude],1) over(partition by trip order by id) as prev_latitude,
    lag([longitude],1) over(partition by trip order by id) as prev_longitude
  from 
    data
)
update data
set
  secsince = DATEDIFF(SECOND, prev_datetime, [datetime]),
  haversine = 6371000* 2 * ASIN ( SQRT (POWER(SIN((Latitude - prev_Latitude)*pi()/180 / 2),2) + COS(Latitude * pi()/180) * COS(prev_Latitude *pi()/180) * POWER(SIN((Longitude - prev_Longitude) *pi()/180 / 2), 2) ) )
from 
  data
  inner join cte on cte.id = data.id

查看SQLFiddle