Trova punti a distanza usando MySQL


20

Ho una tabella mySQL con nome utente, latitudine e longitudine dell'utente. Vorrei ottenere un elenco di utenti che si trovano all'interno del cerchio o del quadrato di una determinata latitudine e longitudine a una determinata distanza. Ad esempio il mio input Lat = 78.3232 e Long = 65.3234 e distanza = 30 miglia. Vorrei ottenere l'elenco degli utenti che si trovano entro 30 miglia di distanza dai punti 78.3232 e 65.3234. È possibile risolverlo con una singola query? Oppure puoi darmi un suggerimento per iniziare a risolvere questa query? Sono nuovo delle informazioni basate sulla geo.


Perché non PostGIS? Se stai avviando un geo project puoi comunque cambiare il tuo stack
simplexio

stackoverflow.com/a/40272394/1281385 Dovrebbe essere utile per velocizzare questa query (se necessario)
exussum,

Risposte:


32

L'istruzione SQL che troverà le 20 posizioni più vicine entro un raggio di 30 miglia dalle coordinate 78.3232, 65.3234. Calcola la distanza in base alla latitudine / longitudine di quella riga e alla latitudine / longitudine target, quindi chiede solo le righe in cui il valore della distanza è inferiore a 30 miglia, ordina l'intera query per distanza e lo limita a 20 risultati. Per cercare per chilometri invece di miglia, sostituire 3959 con 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;

Questo utilizza l'API di Google Maps v3 con un backend MySQL di cui già disponi.

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


Ricevo un errore di sintassi nella mia selezione usando questo, "# 1582 - Conteggio parametri errato nella chiamata alla funzione nativa" radianti "quale potrebbe essere?
bluantinoo,

Trovato: avevo la variabile lng vuota! scusate!
bluantinoo,

Esattamente quello che volevo, ma qual è il sovraccarico delle prestazioni della query per migliaia di record? e la precisione?
Amit Shah,

1
molto meglio sostituirlo con 6371392.896 per la ricerca per metro
Vasilii Suricov

34

La risposta di Mapperz non è valida. Il seno deve essere calcolato dalla latitudine e NON dalla longitudine. Quindi l'istruzione SQL corretta è:

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;

La tua risposta dovrebbe essere ordinata per prima.
Amit Shah,

@AmitShah Se pensi di poter fare un ping all'assistente (@shihabK che non è attivo sul sito da quasi 6 anni) e / o votare per meta.stackexchange.com/questions/268666/…
PolyGeo

Questa dovrebbe essere la risposta accettata.
catbadger,

2

Potrebbe essere base per creare una funzione ... in modo da poterla riutilizzare in altre aree. Inoltre renderebbe la tua query un po 'più pulita ... Almeno questo è il mio 2 centesimi.

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

la risposta verrà annullata se si corregge il codestyle. è la strada giusta
Vasilii Suricov il

0

Ecco la mia variante di query, sembra un po 'più semplice ( 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
È più facile ma ignora il fatto che la terra è curva.
Tim Rijavec,

Hai bisogno di una formula per essere precisi. Forse questo andrebbe bene solo su brevi distanze: D
Jethro il

Lancerai un missile o qualcosa del genere?
Dennis Braga,

1
@DennisBraga - in tal caso, forse questa domanda è fuori tema, più adatta a http://globalthermonuclearwar.stackexchange.com ...?
ashleedawg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.