Znajdź punkty w odległości za pomocą MySQL

20

Mam tabelę mySQL z nazwą użytkownika, szerokością i długością geograficzną użytkownika. Chciałbym uzyskać listę użytkowników, którzy znajdują się w okręgu lub kwadracie o określonej szerokości i długości geograficznej z określoną odległością. Na przykład moje dane wejściowe Lat = 78,3232 i Long = 65,3234, a odległość = 30 mil. Chciałbym uzyskać listę użytkowników, którzy znajdują się w odległości 30 mil od punktów 78.3232 i 65.3234. Czy można to rozwiązać za pomocą pojedynczego zapytania? Czy możesz dać mi wskazówkę, jak rozpocząć rozwiązywanie tego zapytania? Jestem nowy w informacji geograficznej.

shihab K
źródło
Dlaczego nie PostGIS? Jeśli zaczynasz projekt geo, nadal możesz zmienić swój stos
simplexio 14.01.2013
stackoverflow.com/a/40272394/1281385 Powinien być użyteczny w przyspieszeniu tego zapytania (w razie potrzeby)
exussum

Odpowiedzi:

32

Instrukcja SQL, która znajdzie najbliższe 20 lokalizacji, które znajdują się w promieniu 30 mil od współrzędnych 78.3232, 65.3234. Oblicza odległość na podstawie szerokości / długości geograficznej tego wiersza i docelowej szerokości / długości geograficznej, a następnie prosi tylko o wiersze, w których wartość odległości jest mniejsza niż 30 mil, porządkuje całe zapytanie według odległości i ogranicza go do 20 wyników. Aby wyszukiwać według kilometrów zamiast mil, zamień 3959 na 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;

To używa Google Maps API v3 z backendem MySQL, który już masz.

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

Mapperz
źródło
Otrzymuję błąd składniowy w moim zaznaczeniu, używając tego: „# 1582 - Niepoprawna liczba parametrów w wywołaniu funkcji natywnej„ radians ”, co to może być?
bluantinoo,
Znaleziono: miałem zmienną lng pustą! Przepraszam!
bluantinoo
Dokładnie to, czego chciałem, ale jakie jest przeciążenie wydajności zapytania dla tysięcy rekordów? a co z dokładnością?
Amit Shah
1
o wiele lepiej zastąpić go do 6371392.896 do wyszukiwania według metrów
Vasilii Suricov
34

Odpowiedź Mapperza jest nieprawidłowa. Zatokę należy obliczać na podstawie szerokości geograficznej, a NIE długości geograficznej. Tak więc instrukcja Corect SQL to:

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;
Marek Čačko
źródło
Twoja odpowiedź powinna być zamówiona na 1. miejscu.
Amit Shah
@AmitShah Jeśli uważasz, że możesz pingować pytającego (@shihabK, który nie był aktywny na stronie od prawie 6 lat) i / lub głosować na meta.stackexchange.com/questions/268666/...
PolyGeo
To powinna być zaakceptowana odpowiedź.
catbadger
2

Utworzenie funkcji może być podstawą .. abyś mógł z niej ponownie korzystać w innych obszarach. Sprawiłoby to, że twoje zapytanie byłoby trochę czystsze ... Przynajmniej to moje 2 centy.

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
eDriven_Levar
źródło
odpowiedź zostanie pozytywnie oceniona, jeśli naprawisz kodestyle. to właściwa droga
Vasilii Suricov
0

Oto mój wariant zapytania, wydaje się nieco łatwiejszy ( 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`
dexxtr
źródło
4
Jest to łatwiejsze, ale ignoruje fakt, że ziemia jest zakrzywiona.
Tim Rijavec
Potrzebujesz dokładnej formuły. Może to byłoby dobre tylko na krótkich dystansach: D
Jethro
Wystrzelisz pocisk, czy coś?
Dennis Braga
1
@DennisBraga - jeśli tak, to może to pytanie jest nie na temat, lepiej pasuje do http://globalthermonuclearwar.stackexchange.com ...?
ashleedawg