Umkreissuche per SQL Query
Umkreissuchen sind ne feine Sache, aber keine ganz so triviale Angelegenheit. Es braucht ne Masse an Koordinaten in Verbindung mit, sagen wir mal, leichter zu ermittelnden ortspezifischen Daten als GPS Koordinaten oder dem Längen und Breitengrad der derzeitigen Position.
Postleitzahlen würden sich da beispielsweise anbieten. Für eine anständige Datenbasis gibt es da verschiedene Möglichkeiten.
Von kostenfrei bis wahnsinnig teuer ist im Prinzip alles dabei. Zwei kostenlose Datenquellen für Geodaten und eine Umkreissuche möchte ich im folgenden Vorstellen.
Datenquellen
Für den auf avanzu angebotenen Webservice habe ich die Daten von OpenGeoDB verwendet. Die Daten sind für eine herkömmliche Anwendung präzise genug aber leider nur für eine begrenzte Fläche. Der Vorteil, den ich bei dieser Datenquelle sehe liegt darin, dass nicht nur Städte sondern auch Stadtteile aufgeführt sind. Die Stadtteile haben zwar die selben Koordinaten wie die Stadt im ganzen, aber dafür hat man auch nichts dafür bezahlt.
MaxMind – GeoIP bietet einen etwas weniger präzisen aber dafür globalen Dump gratis an, hierzu kann ich nicht wirklich viel mehr sagen, da ich da die Daten für die hier angebotene Umkreissuche nicht ganz so passend waren. Der – wie der Name schon sagt – sehr große vorteil ist der Bezug von Geodaten zu IP Adressen und das sogar relativ exakt. Der monatliche Update-Zyklus hat natürlich auch was für sich.
Die Umkreissuche
Woher auch immer man seine Daten bezieht und in eine Datenbank knallt sei jedem selbst überlassen, jetzt stellt sich natürlich noch die Frage wie man Orte im Umkreis findet. Da die Abfrage selbst der Datenbank relativ viel Rechnerei aufbürdet sollte man etwas vorarbeit leisten.
Die Lägen- und Breitenangaben sind normalerweise in Grad angegeben. Was wir aber brauchen sind Radianten. Die könnte man sich zwar auch on the fly berechnen, aber das kostet Performance die man nicht notwendiger Weise ausgeben muss.
Radiant aus Grad berechnen:
$rad = $grad * (pi()/180);
Für die Abfrage selbst brauchen wir eine Konstante und drei Variablen
- Erdumfang (6371 km – hier $earth)
- Länge (in Rad – hier $lng)
- Breite (in Rad – hier $lat)
- Umkreis (in km – hier $size)
die wir folgendermaßen verwursten:
select alle, felder, die, wir, haben, wollen, $earth * ( 2 * asin( sqrt( power(sin(($lng - lonRad) / 2), 2) + cos($lat) * cos(latRad) * power(sin(($lat - latRad) / 2), 2) ) ) ) as distance from geodata having distance < $size order by distance limit 20
Die Stellschrauben, die bei dieser Abfrage zur Verfügung stehen sind die Umkreisgröße und das Limit. Je nachdem wie sehr man seine Datenbank peinigen will oder darf kann man hier das Feintuning betreiben.
Kommentare: 1
Top Service =)