выберите в пределах 20 километров на основе широты / долготы - PullRequest
7 голосов
/ 03 августа 2011

У меня есть таблица MySQL, структурированная в соответствии с примером ниже:

POSTAL_CODE_ID|PostalCode|City|Province|ProvinceCode|CityType|Latitude|Longitude
7|A0N 2J0|Ramea|Newfoundland|NL|D|48.625599999999999|-58.9758
8|A0N 2K0|Francois|Newfoundland|NL|D|48.625599999999999|-58.9758
9|A0N 2L0|Grey River|Newfoundland|NL|D|48.625599999999999|-58.9758

Теперь я пытаюсь создать запрос, который выберет результаты в пределах выбранных километров от искомого местоположения

так скажем, они ищут «серую реку» и выбирают «найти все результаты в пределах 20 километров»

он, очевидно, должен выбрать «серую реку», но он также должен выбрать все места в пределах 20 километров от серой рекиоснованный на широтах и ​​долготах.

Я действительно понятия не имею, как это сделать.Я прочитал формулу haversine, но не знаю, как применить это к MySQL SELECT.

любая помощь будет высоко ценится.

Ответы [ 4 ]

9 голосов
/ 03 августа 2011
SELECT  *
FROM    mytable m
JOIN    mytable mn
ON      ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
WHERE   m.name = 'grey river'

Если ваша таблица MyISAM, вы можете сохранить свои точки в собственном формате геометрии и создать на нем индекс SPATIAL:

ALTER TABLE mytable ADD position POINT;

UPDATE  mytable
SET     position = POINT(latitude, longitude);

ALTER TABLE mytable MODIFY position NOT NULL;

CREATE SPATIAL INDEX sx_mytable_position ON mytable (position);

SELECT  *
FROM    mytable m
JOIN    mytable mn
ON      MBRContains
                (
                LineString
                        (
                        Point
                                (
                                X(m.position) - 0.009 * 20,
                                Y(m.position) - 0.009 * 20 / COS(RADIANS(X(m.position)))
                                ),
                        Point
                                (
                                X(m.position) + 0.009 * 20,
                                Y(m.position) + 0.009 * 20 / COS(RADIANS(X(m.position))
                                )
                        ),
                mn.position
                )
        AND ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
WHERE   m.name = 'grey river'
1 голос
/ 28 ноября 2016
SELECT `s`.suburb_id,`s`.suburb_name,`s`.lat,`s`.long, (((acos(sin(($lat*pi()/180)) * sin((s.lat*pi()/180))+cos(($lat*pi()/180)) * cos((s.lat*pi()/180)) * cos((($long - s.long)*pi()/180))))*180/pi())*60*1.1515*1.609344) AS distance FROM (`mst_suburbs` as s) HAVING distance <= 20 ORDER BY `s`.suburb_id DESC

Этот запрос работает для меня, чтобы получить все широты длиной от 12 км. У меня есть mst_suburbs таблица май, которая имеет столбцы lat и long.мои две переменные php. И я передаю желаемый лат, длинный, чтобы получить список ближайших 12 км лат из mst_suburb.Вам просто нужно изменить имя столбца в соответствии с вашей таблицей и передать лат, long для запроса.

0 голосов
/ 03 августа 2011

Вы просто берете формулу haversine и применяете ее следующим образом:

SELECT   *,
         6371 * ACOS(SIN(RADIANS( $lat1 )) * SIN(RADIANS(`Latitude`)) +
         COS(RADIANS( $lat1 )) * COS(RADIANS(`Latitude`)) * COS(RADIANS(`Longitude`) -
         RADIANS( $lon1 ))) AS `distance`
FROM     `table`
WHERE    `distance` <= 20
ORDER BY `distance` ASC

Замените $lat1 и $lon1 широтой и долготой, с которыми вы хотите сравнить.

0 голосов
/ 03 августа 2011

Это немного сложный алгоритм, но вот ссылка на одно решение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...