特定半径内的zipcodes

时间:2017-04-11 01:19:16

标签: sql ms-access latitude-longitude zipcode great-circle

我正在寻找一个SQL查询,让我检索特定半径内的Zipcodes。

我有一个名为tblZip的表,其中包含以下列:ZipcodeLat(纬度),Long(经度)。

tblZip

Zipcode    | Lat    | Long
Short Text | Number | Number

我已经检查了一些建议使用Great-circle Distance的其他答案,但我似乎不明白它是如何工作的。我只是看到了从弧度和弧度的所有转换,我真的很头疼,我真的试图理解它,但我对数学很糟糕。

感谢您的帮助和指导。

PS:我正在使用Microsoft Access数据库。

1 个答案:

答案 0 :(得分:3)

考虑在VBA函数中使用hasrsine距离公式(借用here)。然后在SQL查询中调用它。甚至可以根据您的需要使用WHERE子句按距离过滤您的查询。请注意:此解决方案仅适用于MSAccess.exe程序。您将无法通过ODBC / OLEDB从外部调用它。

由于您需要比较地理编码,因此下面的SQL查询使用交叉连接,其中每条记录与表中的每个其他记录进行比较。此外,查询避免了反向重复和相同匹配的配对,从而减小了大小。但是要小心,如果表格很大,因为自我上的交叉连接返回N 2 记录,即在重复过滤之前。

SQL (距离为5公里或更短的邮政编码配对)

SELECT z1.Zipcode, z2.Zipcode, 
       GetDistance(z1.Lat, z1.Lon, z2.Lat, z2.Lon) As km_distance
FROM tblZip z1, tblZip z2
WHERE z1.Zipcode > z2.Zipcode
AND GetDistance(s1.lat, s1.lon, s1.lat, s2.lon) <= 5;

VBA (保存在独立模块中)

Function GetDistance(lat1Degrees As Double, lon1Degrees As Double, lat2Degrees As Double, lon2Degrees As Double) As Double

    Dim earthSphereRadiusKilometers As Double
    Dim kilometerConversionToMilesFactor As Double
    Dim lat1Radians As Double
    Dim lon1Radians As Double
    Dim lat2Radians As Double
    Dim lon2Radians As Double
    Dim AsinBase As Double
    Dim DerivedAsin As Double

    'Mean radius of the earth (replace with 3443.89849 to get nautical miles)
    earthSphereRadiusKilometers = 6371

    'Convert kilometers into miles (replace 0.621371 with 1 to keep in kilometers)
    kilometerConversionToMilesFactor = 0.621371

    'Convert each decimal degree to radians
    lat1Radians = (lat1Degrees / 180) * (4 * ATN(1))
    lon1Radians = (lon1Degrees / 180) * (4 * ATN(1))
    lat2Radians = (lat2Degrees / 180) * (4 * ATN(1))
    lon2Radians = (lon2Degrees / 180) * (4 * ATN(1))

    AsinBase = Sin(Sqr(Sin((lat1Radians - lat2Radians) / 2) ^ 2 + Cos(lat1Radians) * Cos(lat2Radians) * Sin((lon1Radians - lon2Radians) / 2) ^ 2))
    DerivedAsin = (AsinBase / Sqr(-AsinBase * AsinBase + 1))

    'Get distance from [lat1,lon1] to [lat2,lon2]
    GetMiles = Round(2 * DerivedAsin * (earthSphereRadiusKilometers * kilometerConversionToMilesFactor), 2)

End Function