Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Entfernungsberechnungen in MySQL-Abfragen

Option 1:Führen Sie die Berechnung auf der Datenbank durch, indem Sie zu einer Datenbank wechseln, die GeoIP unterstützt.

Option 2:Führen Sie die Berechnung in der Datenbank durch, indem Sie eine gespeicherte Prozedur wie diese verwenden:

CREATE FUNCTION calcDistance (latA double, lonA double, latB double, LonB double)
    RETURNS double DETERMINISTIC
BEGIN
    SET @RlatA = radians(latA);
    SET @RlonA = radians(lonA);
    SET @RlatB = radians(latB);
    SET @RlonB = radians(LonB);
    SET @deltaLat = @RlatA - @RlatB;
    SET @deltaLon = @RlonA - @RlonB;
    SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) +
    COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2);
    RETURN 2 * ASIN(SQRT(@d)) * 6371.01;
END//

Wenn Sie einen Index für Längen- und Breitengrad in Ihrer Datenbank haben, können Sie die Anzahl der zu berechnenden Berechnungen reduzieren, indem Sie in PHP eine anfängliche Begrenzungsbox ($minLat, $maxLat, $minLong und $maxLong) ausarbeiten und einschränken die Zeilen zu einer Teilmenge Ihrer darauf basierenden Einträge (WHERE Breitengrad BETWEEN $minLat AND $maxLat AND Längengrad BETWEEN $minLong AND $maxLong). Dann muss MySQL nur die Entfernungsberechnung für diese Teilmenge von Zeilen ausführen.

Wenn Sie einfach eine gespeicherte Prozedur verwenden, um die Entfernung zu berechnen), muss SQL immer noch jeden Datensatz in Ihrer Datenbank durchsuchen und die Entfernung für jeden Datensatz in Ihrer Datenbank berechnen, bevor es entscheiden kann, ob diese Zeile zurückgegeben oder verworfen werden soll .

Da die Berechnung relativ langsam ausgeführt wird, wäre es besser, wenn Sie die Menge der zu berechnenden Zeilen reduzieren und Zeilen eliminieren könnten, die eindeutig außerhalb des erforderlichen Abstands liegen, sodass wir nur die teure Berechnung für ausführen eine kleinere Anzahl von Zeilen.

Wenn Sie bedenken, dass Sie im Grunde genommen einen Kreis auf einer Karte zeichnen, der auf Ihren Ausgangspunkt zentriert ist und einen Entfernungsradius aufweist; dann identifiziert die Formel einfach, welche Zeilen in diesen Kreis fallen ... aber es muss immer noch jede einzelne Zeile überprüft werden.

Die Verwendung eines Begrenzungsrahmens ist wie das Zeichnen eines Quadrats auf der Karte, wobei sich die linke, rechte, obere und untere Kante im entsprechenden Abstand von unserem Mittelpunkt befinden. Unser Kreis wird dann innerhalb dieses Kästchens gezeichnet, wobei die nördlichsten, östlichsten, südlichsten und westlichsten Punkte des Kreises die Ränder des Kästchens berühren. Einige Zeilen fallen außerhalb dieses Felds, sodass SQL sich nicht einmal die Mühe macht, den Abstand für diese Zeilen zu berechnen. Es berechnet nur den Abstand für die Zeilen, die in den Begrenzungsrahmen fallen, um zu sehen, ob sie auch in den Kreis fallen.

In Ihrem PHP (schätzen Sie, Sie führen PHP über den $-Variablennamen aus) können wir eine sehr einfache Berechnung verwenden, die den minimalen und maximalen Breiten- und Längengrad basierend auf unserer Entfernung berechnet, und diese Werte dann in der WHERE-Klausel Ihres SQL-Befehls festlegen Erklärung. Dies ist praktisch unsere Box, und alles, was außerhalb davon fällt, wird automatisch verworfen, ohne dass die Entfernung tatsächlich berechnet werden muss.

Auf Movable Type finden Sie dazu eine gute Erklärung (mit PHP-Code). Webseite das sollte eine wichtige Lektüre für jeden sein, der plant, GeoPositioning-Arbeiten in PHP durchzuführen.

BEARBEITEN Der Wert 6371,01 in der gespeicherten Prozedur calcDistance ist der Multiplikator, mit dem Sie ein zurückgegebenes Ergebnis in Kilometern erhalten. Verwenden Sie geeignete alternative Multiplikatoren, wenn Sie Meilen, Seemeilen, Meter oder was auch immer erhalten möchten