Я предполагаю, что вы используете SQL 2008 с поддержкой пространственных данных.
Похоже, у вас может быть несколько заданий на одном сайте (т. Е. Адрес), поэтому я бы создал таблицу заданий с внешним ключом, указывающим на таблицу сайтов, содержащую столбцы для всей информации об адресе и дополнительный столбец. типа География .
Вам потребуется настроить процесс для заполнения столбца с типом географии информацией о геокоде (т. Е. Широтой и долготой адреса), Пакетный геокодер MapPoint - это процесс SSIS, использующий MapPoint (сейчас Карты Bing) Сервис и может стать хорошей отправной точкой для разработки вашего собственного процесса.
Как только вы сможете получить геокод для адреса, обновление таблицы SQL становится простым.
UPDATE Sites
SET GeoLocation = GEOGRAPHY::POINT(@latitude, @longitude, 4326)
WHERE SiteID = @siteId
Независимо от того, где в вашем конвейере вы интегрируете геокодер, я бы порекомендовал вам абстрагировать его таким образом, чтобы вы могли легко сменить поставщика услуг Geocode или указать, какой из них использовать во время выполнения, поскольку все сервисы имеют разные схемы ценообразования. и это может оказаться финансово выгодным использовать один над другим. Например, Google предлагает 912 500 бесплатных запросов в год по 2500 макс. В день без ограничения сеансов, тогда как Bing предлагает только 500 000 запросов в год без ограничения в день, но с ограничением в 125 000 сеансов. Так что для больших пакетных запросов Bing выигрывает, но для каждого элемента или случайных запросов Google выходит на первое место. В конце концов, качество данных этих служб сопоставимо, поэтому не стоит менять источник, чтобы избежать платы.
После импорта данных и заполнения геокодов становится легко вычислять расстояния и находить ближайших соседей.
DECLARE @Sites TABLE ( SiteId INT )
--Get the site ids you care about
INSERT INTO @Sites
SELECT SiteId FROM Jobs WHERE Status = 'Open'
/*
* For each site in your table variable @Sites, this will list
* all the other sites in the variable in order of distance.
*/
SELECT p.SiteId
, s.SiteId
, p.GeoLocation.STDistance(s.SiteId) * 0.001 AS [Distance (Kilometers)] --https://www.google.com/search?q=meters+to+kilometers
, p.GeoLocation.STDistance(s.SiteId) * 0.000621371192 AS [Distance (Miles)] --https://www.google.com/search?q=meters+to+miles
FROM Sites AS [p]
JOIN Sites AS [s]
ON s.SiteId != p.SiteId
AND s.SiteId IN (SELECT SiteId FROM @Sites)
WHERE p.SiteId IN (SELECT SiteId FROM @Sites)
ORDER BY p.SiteId, s.SiteId, p.GeoLocation.STDistance(s.GeoLocation)