考虑在 VBA 函数中使用半正弦距离公式(在此处借用)。然后在您的 SQL 查询中调用它。甚至可以WHERE
根据您的需要按距离与子句过滤您的查询。请注意:此解决方案仅适用于 MSAccess.exe 程序。您将无法通过 ODBC/OLEDB 从外部调用它。
由于您需要比较地理编码,因此下面的 SQL 查询使用交叉连接,其中每条记录都与表中的所有其他记录进行比较。此外,查询避免了反向重复和相同匹配的配对,从而减少了大小。但要小心,如果表很大,因为 self 上的交叉连接返回 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