2015-09-06 5 views
1

У меня есть база данных SQL, в которую мне назначены координаты (lat, long). Я хотел бы спросить те точки, которые лежат в радиусе 5 км от моей точки внутри. Интересно, как построить запрос таким образом, чтобы не собирать ненужные записи?SQL Поиск координат, принадлежащих окружности

+1

Какой двигатель и версия базы данных? что ты уже испробовал? – duffn

+0

Я использую базу данных MySQL на основе Boot Spring/Hibernate. Я не знаю, нужно ли мне загружать все записи, а затем рассчитать их расстояние от центра, если я могу немедленно вытащить запрос. – lukassz

+0

Какая точность вам нужна? можете ли вы предположить, что 0,05 в лат, длиной около 5 км? – Balinti

ответ

1

Поскольку вы говорите о небольших расстояниях около 5 км, и мы, вероятно, не находимся в непосредственной близости от северного или южного полюса, мы можем работать с аппроксимированной сеткой долготы и широты. Каждая степень в latidude эквивалентна расстоянию km_per_lat=6371km*2*pi/360degrees = 111.195km. Расстояние между двумя продольными линиями, которые 1 степени друг от друга, зависит от фактической широты:

km_per_long=km_per_lat * cos(lat) 

В районах здесь, в Северной Германии (51 градус северной широты) это значение будет около 69.98km.

Таким образом, предполагая, что мы заинтересованы в небольших расстояниях вокруг lat0 и long0 мы можем смело предположить, что коэффициенты перевода для продольных и широтных углов будут оставаться такими же, и мы можем просто применить формулу

SELECT 111.195*sqrt(power([email protected],2) 
        +power(cos(pi()/180*@lat0)*([email protected]),2)) dist_in_km FROM tbl 

С вами хотите использовать формулу в предложении о вашей выберите WHERE вы можете использовать следующее:

SELECT * FROM tbl 
WHERE 111.195*sqrt(power([email protected],2) 
        +power(cos(pi()/180*@lat0)*([email protected]),2)) < 5 

ЗЕЬЕСТ будет работать для значений широты и долготы данных в степени (в десятичной системе счисления). Из-за этого мы должны преобразовать значение внутри функции cos() в радианы, умножив его на pi()/180.

Если вам приходится работать с большими расстояниями (> 500км), то это, вероятно, лучше применить соответствующую формулу расстояния, используемые в навигации, как

cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat) 

После расчета фактического угла дельта, применяя acos() вам просто умножьте что значение по радиусу Земли R = 6371km = 180/pi()*111.195km и у вас есть требуемое расстояние (см здесь: Wiki: great circle distance)

Update (ответ на комментарий):

Не знаете, что вы намерены делать.Если есть только один референтную позицию вы хотите сравнить против, то вы можете, конечно, Прекомпилировать расчет расстояния немного как

SELECT @lat0:=51,@long0:=-9; -- assuming a base position of: 51°N 9°E 
SELECT @rad:=PI()/180,@fx:[email protected]*6371,@fy:[email protected]*cos(@rad*@lat0); 

Ваш расчет расстояния будет упрощать только

SELECT @dist:=sqrt(power(@fx*([email protected]),2)+power(@fy*([email protected]),2)) 

с током позиции в lat и long (больше не требуется косинусных функций). Все зависит от того, хотите ли вы сначала сохранить все входящие позиции в базе данных или хотите ли вы выполнять вычисления где-то вне Spring, Java или любого другого языка, который вы используете. Уравнения есть и просты в использовании.

+0

Я хочу использовать его в приложениях Boot Spring с помощью Hibernate. Платит ли подсчет расстояния непосредственно в базе данных? Лучше ли получить все записи из базы данных, а затем выбрать их? – lukassz

-1

Я бы пошел с Евклидом. dist=sqrt(power(x1-x2,2)+power(y1-y2,2)). Он работает повсюду. Возможно, вам нужно добавить преобразование в координаты x/y, если степени не могут быть легко переведены в километры.

Чем вы можете идти и выбрать все, что вам нравится WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5). Теперь вы можете проверить результаты с Euklid.

С оптимизацией результата результата сначала можно получить лучшие результаты. Возможно, есть способ взять Euklid и SQL.

+0

Декартовое расстояние не подходит для расчетов на расстоянии по широте, за исключением местоположений, очень близких друг к другу и экватора. –

+0

Ну, на мой взгляд, 5 км очень близко. И, как я уже сказал, может возникнуть необходимость в преобразовании, которое cars10 разработал очень хорошо ;-) – queuverflow

Смежные вопросы