У меня есть вопрос об использовании Microsoft Access для сортировки моих клиентов (см. Первую таблицу ниже) по расстоянию от введенного пользователем почтового индекса. Я использую формулу расстояния большого круга (см. Код ниже), чтобы вычислить расстояние между почтовыми индексами. У меня есть таблица каждого текущего почтового индекса в США с его координатами широты и долготы (см. Вторую таблицу ниже). Функция берет почтовый индекс каждого клиента и захватывает широту и долготу из первой и второй таблиц и использует это рассчитать расстояние между каждым. Вот запущенный мной SQL-запрос, который вызывает GreatCircleDistance Формула:
PARAMETERS [Zip Code] IEEEDouble;
SELECT Clinics.Clinic, [US Zip Codes].ZIP,
[US Zip Codes].LAT, [US Zip Codes].LNG,
GreatCircleDistance([Zip Code],[LAT],[LNG],True,True) AS Distance
FROM [US Zip Codes] INNER JOIN Clinics ON [US Zip Codes].ZIP = Clinics.[Clinic ZIP];
Формула Великого окружного расстояния, используемая для этого запроса, показана ниже:
Private Const C_RADIUS_EARTH_KM As Double = 6370.97327862
Private Const C_RADIUS_EARTH_MI As Double = 3958.73926185
Private Const C_PI As Double = 3.14159265358979
Function GreatCircleDistance(ZipCode As Double, _
Latitude2 As Double, Longitude2 As Double, _
ValuesAsDecimalDegrees As Boolean, _
ResultAsMiles As Boolean) As Double
Dim lat1 As Double
Dim lat2 As Double
Dim long1 As Double
Dim long2 As Double
Dim X As Long
Dim Delta As Double
If ValuesAsDecimalDegrees = True Then
X = 1
Else
X = 24
End If
' convert to decimal degrees
'POTENTIAL PROBLEM
lat1 = DLookup("[US Zip Codes].LAT", "[US Zip Codes]", "[US Zip Codes].ZIP = '" & ZipCode & "'") * X
long1 = DLookup("[US Zip Codes].LNG", "[US Zip Codes]", "[US Zip Codes].ZIP = '" & ZipCode & "'") * X
'POTENTIAL PROBLEM
lat2 = Latitude2 * X
long2 = Longitude2 * X
' convert to radians: radians = (degrees/180) * PI
lat1 = (lat1 / 180) * C_PI
lat2 = (lat2 / 180) * C_PI
long1 = (long1 / 180) * C_PI
long2 = (long2 / 180) * C_PI
' get the central spherical angle
Delta = ((2 * ArcSin(Sqr((Sin((lat1 - lat2) / 2) ^ 2) + _
Cos(lat1) * Cos(lat2) * (Sin((long1 - long2) / 2) ^ 2)))))
If ResultAsMiles = True Then
GreatCircleDistance = Delta * C_RADIUS_EARTH_MI
Else
GreatCircleDistance = Delta * C_RADIUS_EARTH_KM
End If
End Function
Function ArcSin(X As Double) As Double
' VBA doesn't have an ArcSin function. Improvise.
ArcSin = Atn(X / Sqr(-X * X + 1))
End Function
Вот первая таблица со всеми моими клиентами. Я добавил только три для простоты, но в файле около 2000 записей:
Clinic City State Clinic ZIP
Clinic #1 Lakeland FL 33809
Clinic #2 Smyrna TN 37167
Clinic #3 Kissimmee FL 34747
...
Вот вторая таблица, в которой есть каждый почтовый индекс США. Всего зарегистрировано чуть более 41 000 почтовых индексов:
ID ZIP LAT LNG
1 00501 40.8133 -73.0476
2 00601 18.18 -66.7522
3 00602 18.3607 -67.1752
4 00603 18.4544 -67.122
...
Теперь этот метод работает, но он занимает много времени, чтобы вычислить расстояние между входным почтовым индексом и почтовым индексом каждого из 2000-тысячных клиентских почтовых индексов. Я думаю, что проблема в формуле Великого окружного расстояния, когда я использую функцию DLookUp , чтобы получить широту и долготу введенного пользователем почтового индекса. Кто-нибудь знает, как я могу уменьшить время вычислений для этого? Спасибо