【发布时间】:2023-06-02 05:56:01
【问题描述】:
使用 SQL Server 2014。
我正在尝试让 SQL Server 计算世界各地机场之间的距离,以公里、英里和海里为单位。大多数情况下,下面的方法有效,但是当距离超过 10,000Km 时它似乎会失败(尽管这只是一个假设)。
DECLARE @Radius_Km AS FLOAT
DECLARE @Radius_Mi AS FLOAT
DECLARE @Radius_Nm AS FLOAT
DECLARE @Pi AS FLOAT
DECLARE @D2R AS FLOAT
SET @Radius_Km = '6370.97327862'
SET @Radius_Mi = '3958.73926185'
SET @Radius_Nm = '3440.05036642'
SET @Pi = '3.14159265358979'
SET @D2R = @Pi / 180;
WITH RawData AS
(
SELECT DISTINCT Sched.AirlineName, Sched.AirlineIATA, Sched.AirlineICAO, Sched.FlightNo,
Sched.DepartureAirportName, Sched.DepartureAirportIATA, DepAprt.AirportICAO AS [DepartureAirportICAO],
DepAprt.Latitude AS [DepartureAirportLatitude], DepAprt.Longitude AS [DepartureAirportLongitude],
Sched.ArrivalAirportName, Sched.ArrivalAirportIATA, ArrAprt.AirportICAO AS [ArrivalAirportICAO],
ArrAprt.Latitude AS [ArrivalAirportLatitude], ArrAprt.Longitude AS [ArrivalAirportLongitude]
FROM VAS_Live.dbo.RawData_FR24 AS Sched
LEFT JOIN VAS_Live.dbo.ReferenceData_Airports AS DepAprt
ON Sched.DepartureAirportIATA = DepAprt.AirportIATA
LEFT JOIN VAS_Live.dbo.ReferenceData_Airports AS ArrAprt
ON Sched.ArrivalAirportIATA = ArrAprt.AirportIATA
),
RadianConvert AS
(
SELECT *,
((DepartureAirportLatitude / 180) * @Pi) AS [DALat],
((DepartureAirportLongitude / 180) * @Pi) AS [DALon],
((ArrivalAirportLatitude / 180) * @Pi) AS [AALat],
((ArrivalAirportLongitude / 180) * @Pi) AS [AALon]
FROM RawData
),
CentralSphericalAngle AS
(
SELECT *,
(Sin(DALat) * Sin(AALat)) + (Cos(DALat) * Cos(AALat) * Cos(AALon - DALon)) AS [Test]
FROM RadianConvert
),
TestCTE AS
(
SELECT *,
@Radius_Mi * ATAN(SQRT(1 - POWER(Test, 2)) / Test) AS [Test2]
FROM CentralSphericalAngle
)
SELECT *
FROM TestCTE
WHERE DepartureAirportIATA = 'LHR' AND ArrivalAirportIATA = 'SIN'
对于上面的例子,LHR Lat & Lon 如下:
51.4775 -0.461389
SIN 经纬度如下:
1.35019 103.994
我已经知道距离大概是:
公里 - 10,883
小米 - 6,762
Nm - 5,876
知道为什么 SQL 给我 -5674 吗?
我曾经使用 VBA 和 Excel 来计算这些数据,这很有效。我注意到 Arrival AALat 和 DALon 在转换为弧度时计算不正确 - 但我不知道为什么。
谢谢
马修
【问题讨论】:
-
1) 使用
GEOGRAPHY数据类型 2) 使用.STDistance3) 避免复杂的公式、弧度/度数之间的重新计算等 -
地理数据类型需要一个绝对年龄来计算。当我需要为数千行完成此操作时 - 恐怕这不是一个解决方案 - 除非您有任何代码您希望我专门尝试并报告回来?
-
你在这里使用什么公式?对我来说,它看起来不像haversine。对于空间,试试这个:SELECT *, GEOGRAPHY::POINT(DepAprt.Latitude, DepAprt.Longitude, 4326).STDistance(GEOGRAPHY::Point(ArrAprt.Latitude, ArrAprt.Longitude,4326)) FROM RawData
-
好的,试试这个,我得到 10887730.8812865 作为答案。知道我应该怎么做才能将其显示为 Km、Mi 和 Nm?
-
“地理需要一个绝对年龄来计算”。你那里有基准吗?我的经历正好相反。特别是如果您已经创建并存储了地理点。快速浏览一下您的架构,您肯定可以(如果您想保留纬度和经度,则作为计算列)。
标签: sql sql-server sql-server-2014