我正在使用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
答案 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。