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

Finden Sie alle Postleitzahlen innerhalb der angegebenen Entfernung von einer Postleitzahl

Hier ist etwas, das ich vor einiger Zeit geschrieben habe und das Sie vielleicht in die richtige Richtung führt.

Während Sie nach VB.Net gefragt haben, brauchen Sie wirklich eine Abfrage, die einen "Great Circle ausführt Entfernung " Berechnung zur Bestimmung der Entfernung zwischen zwei durch Längen- und Breitengrad identifizierten Punkten.

Gehen Sie also von den folgenden Annahmen aus:

  1. Ihre Postleitzahlendaten befinden sich in einer einzigen Tabelle.
  2. Diese Tabelle hat Attribute für Längen- und Breitengrad, die ungefähr dem Schwerpunkt der Postleitzahl entsprechen

Sie könnten eine LINQ-to-SQL-Abfrage verwenden, die die gewünschte Ergebnismenge erzeugt, indem Sie so etwas verwenden

Const EARTH_RADIUS As Single = 3956.0883313286095
Dim radCvtFactor As Single = Math.PI / 180
Dim zipCodeRadius As Integer = <Your Radius Value>

Dim zipQry = From zc In db.ZipCodes 
             Where zc.Zip = "<Your Zip Code>" _
             Select zc.Latitude, 
                    zc.Longitude, 
                    ZipLatRads = RadCvtFactor * zc.Latitude, 
                    ZipLonRads = RadCvtFactor * zc.Longitude
Dim zipRslt = zipQry.SingleOrDefault()
If zipRslt IsNot Nothing Then
    Dim zcQry = From zc In db.ZipCodes _
                Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
                And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _
                And Math.Abs(EARTH_RADIUS * (2 * Math.Atan2(Math.Sqrt(Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
                Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
                Math.Pow(Math.Sin(((RadCvtFactor * zc.Longitude) - zipRslt.ZipLonRads) / 2), 2)), _
                Math.Sqrt(1 - Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
                Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
                Math.Pow(Math.Sin((RadCvtFactor * zc.Longitude) / 2), 2))))) <= zipCodeRadius _
                Select zc
End If

Es sieht kompliziert aus, weil es ist. Hier auf SO gibt es viel klügere Leute, die den Algorithmus erklären können. Ich habe dies lediglich aus einem SQL-Code implementiert, den ich im Internet gefunden habe - ich kann mich nicht erinnern, woher. Eine Google-Suche sollte Sie dorthin führen.

Die erste Abfrage (zipQry) gibt den Breiten- und Längengrad der Start-Postleitzahl in Grad und Bogenmaß zurück. Diese Ergebnisse werden dann verwendet, um die zweite Abfrage auszuführen.

Der erste Teil der WHERE-Klausel in der zweiten Abfrage:

Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _

Nur die Liste der zu untersuchenden Postleitzahlen eingegrenzt, wodurch die Abfrage viel schneller ausgeführt wird. Es addiert einen willkürlichen Betrag zu Breite und Länge, sodass Sie nicht alle Postleitzahlen in Ohio überprüfen, wenn Sie nach einem Umkreis in Kalifornien suchen. Der Rest ist alles Teil des oben erwähnten Great Circle Distance-Algorithmus.

Dies hätte wahrscheinlich in einer Abfrage für mehr Effizienz getan werden können, aber ich brauchte es damals auf diese Weise, die Gründe sind mir jetzt entfallen.