Знайдіть точки на відстані за допомогою MySQL


20

У мене є таблиця mySQL з ім'ям користувача, широтою та довготою користувача. Я хотів би отримати список користувачів, які знаходяться всередині кола або квадрата заданої широти та довготи із заданою відстані. Наприклад, мій вхід Lat = 78,3232 і Long = 65,3234 та відстань = 30 миль. Я хотів би отримати список користувачів, які знаходяться в 30 милях від точки 78.3232 та 65.3234. Чи можна вирішити це за допомогою одного запиту? Або ви можете дати мені підказку почати вирішувати цей запит? Я новачок у географічній інформації.


Чому б не PostGIS? Якщо ви починаєте
геопроект,

stackoverflow.com/a/40272394/1281385 Має бути корисним для прискорення цього запиту (якщо потрібно)
exussum

Відповіді:


32

Оператор SQL, який знайде найближчі 20 локацій, які знаходяться в радіусі 30 миль до координати 78.3232, 65.3234. Він обчислює відстань на основі широти / довготи цього рядка та цільової широти / довготи, а потім запитує лише рядки, де значення відстані менше 30 миль, впорядковує весь запит на відстань і обмежує його на 20 результатів. Щоб шукати кілометри замість миль, замініть 3959 на 6371.

SELECT
  id, (
    3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
  ) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Для цього використовується API Карт Google v3 із сервісом MySQL, який у вас уже є.

https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql


Я отримую синтаксичну помилку в моєму виборі, використовуючи це, "# 1582 - Неправильний підрахунок параметрів у виклику до нативної функції" радіани ", що це може бути?
bluantinoo

Знайдено: у мене змінна lng порожня! вибачте!
bluantinoo

Саме те, що я хотів, але що виконання запитів перевантажує тисячі записів? а як щодо точності?
Аміт Шах

1
набагато краще замінити його на 6371392.896 для пошуку за метрами
Василь Суріцов

34

Відповідь Mapperz недійсна. Синус потрібно обчислювати з широти, а НЕ від довготи. Отже, оператор SQL corect:

SELECT
    id, (
      3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;

Вашу відповідь слід замовити 1-го.
Аміт Шах

@AmitShah Якщо ви думаєте, що ви можете подзвонити підозрюваному (@shihabK, який не був активним на сайті майже 6 років) та / або проголосувати за meta.stackexchange.com/questions/268666/…
PolyGeo

Це має бути прийнятою відповіддю.
catbadger

2

Це може бути базовим для створення функції .. так що ви можете повторно використовувати його в інших інших областях. Також зробить ваш запит трохи чистішим ... Принаймні, це мої 2 копійки.

DELIMITER $$

create function calcDistance(lat float, lng float, pnt_lat float, pnt_lng float)

Returns float
BEGIN

Declare dist float;
SET dist =
  3959 * acos (
  cos ( radians(pnt_lat) )
  * cos( radians( lat ) )
  * cos( radians( lng ) - radians(pnt_lng) )
  + sin ( radians(pnt_lat) )
  * sin( radians( lat ) )
);

RETURN dist;

END

відповідь буде застосована, якщо ви виправите стиль коду. це правильно
Василь Суріцов

0

Ось мій варіант запиту, здається трохи легшим ( http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql )

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`

4
Простіше, але ігнорує той факт, що земля вигнута.
Тім Ріявек

Потрібна формула, щоб бути точною. Можливо, це було б добре лише на коротких відстанях: D
Jethro

Я зімлю ракету, чи щось?
Денніс Брага

1
@DennisBraga - якщо так, то, можливо, це питання поза темою, краще підходить для http://globalthermonuclearwar.stackexchange.com ...?
ashleedawg
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.