Finden Sie mit MySQL Punkte in einiger Entfernung

20

Ich habe eine mySQL-Tabelle mit Benutzername, Breite und Länge des Benutzers. Ich möchte eine Liste von Benutzern erhalten, die sich innerhalb des Kreises oder Quadrats eines bestimmten Breiten- und Längengrads mit einem bestimmten Abstand befinden. Zum Beispiel meine Eingabe Lat = 78,3232 und Long = 65,3234 und Entfernung = 30 Meilen. Ich möchte die Liste der Benutzer erhalten, die sich innerhalb von 30 Meilen Entfernung von den Punkten 78.3232 und 65.3234 befinden. Ist es möglich, dies mit einer einzigen Abfrage zu lösen? Oder können Sie mir einen Tipp geben, wie ich diese Frage lösen kann? Ich bin neu in den geobasierten Informationen.

shihab K
quelle
Warum nicht PostGIS? Wenn Sie ein Geo-Projekt starten, können Sie Ihren Stack trotzdem ändern
simplexio
stackoverflow.com/a/40272394/1281385 Sollte hilfreich sein, um diese Abfrage zu beschleunigen (falls erforderlich)
exussum

Antworten:

32

Die SQL-Anweisung, mit der die nächsten 20 Positionen innerhalb eines Radius von 30 Meilen zur Koordinate 78.3232, 65.3234 gefunden werden. Es berechnet die Entfernung basierend auf der Breite / Länge dieser Zeile und der geografischen Breite / Länge des Ziels und fragt dann nur Zeilen ab, in denen der Entfernungswert weniger als 30 Meilen beträgt, ordnet die gesamte Abfrage nach Entfernung und begrenzt sie auf 20 Ergebnisse. Um nach Kilometern anstatt nach Meilen zu suchen, ersetzen Sie 3959 durch 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;

Hierbei wird die Google Maps API v3 mit einem MySQL-Backend verwendet, über das Sie bereits verfügen.

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

Mapperz
quelle
Ich erhalte einen Syntaxfehler in meiner Auswahl, wenn ich dies verwende. "# 1582 - Falsche Parameteranzahl beim Aufruf der nativen Funktion 'radians', was könnte das sein?
bluantinoo
Gefunden: Ich hatte die Variable lng leer! Es tut uns leid!
Bluantinoo
Genau das, was ich wollte, aber was ist die Überlastung der Abfrageleistung für Tausende von Datensätzen? und wie steht es mit der Genauigkeit?
Amit Shah
1
viel besser, es zu 6371392.896 für die Suche nach Metern zu ersetzen
Vasilii Suricov
34

Die Antwort von Mapperz ist ungültig. Der Sinus muss aus dem Breitengrad und NICHT aus dem Längengrad berechnet werden. Die korrekte SQL-Anweisung lautet also:

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
quelle
Ihre Antwort sollte zuerst bestellt werden.
Amit Shah
@AmitShah Wenn Sie der Meinung sind, dass Sie den Fragesteller (@shihabK, der seit fast 6 Jahren nicht mehr auf der Website aktiv ist) anpingen
PolyGeo
Dies sollte die akzeptierte Antwort sein.
catbadger
2

Es kann eine Basis sein, um eine Funktion zu erstellen, damit Sie sie in anderen Bereichen wiederverwenden können. Würde auch deine Abfrage ein bisschen sauberer machen ... Zumindest sind das meine 2 Cent.

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
quelle
Die Antwort wird positiv bewertet, wenn Sie den Codestyle korrigieren. es ist der richtige Weg
Vasilii Suricov
0

Hier ist meine Variante der Abfrage, scheint ein bisschen einfacher ( 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
quelle
4
Es ist einfacher, ignoriert aber die Tatsache, dass die Erde gekrümmt ist.
Tim Rijavec,
Benötigen Sie eine Formel, um genau zu sein. Vielleicht wäre das nur auf kurzen Strecken gut: D
Jethro
Wirst du eine Rakete abschießen oder so?
Dennis Braga
1
@DennisBraga - wenn ja, dann ist diese Frage vielleicht nicht zum Thema, besser geeignet für http://globalthermonuclearwar.stackexchange.com ...?
Ashleedawg