sql >> Databasteknik >  >> RDS >> Mysql

Hitta alla postnummer inom angivet avstånd från ett postnummer

Här är något jag skrev för ett tag sedan som kan få dig i rätt riktning.

Medan du bad om VB.Net, vad du verkligen behöver är en fråga som gör en "Great Circle Avstånd " beräkning för att bestämma avståndet mellan två punkter identifierade av latitud och longitud.

Så, gör följande antaganden:

  1. Din postnummer finns i en enda tabell.
  2. Nämnda tabell har attribut för lat och lon som är den ungefärliga tyngdpunkten för postnumret

Du kan använda en LINQ till SQL-fråga som producerar den önskade resultatuppsättningen med något sånt här

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

Det ser komplicerat ut, för det är det. Det finns mycket smartare människor här på SO som kan förklara algoritmen. Jag implementerade bara detta från någon SQL-kod jag hittade på internet - jag kan inte minnas varifrån. En sökning på Google borde ta dig dit.

Den första frågan (zipQry) returnerar lat och lon för startpostnumret i både grader och radianer. Dessa resultat används sedan för att köra den andra frågan.

Den första delen av WHERE-satsen i den andra frågan:

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) _

Har precis minskat listan över postnummer som ska undersökas, vilket gör att frågan körs mycket snabbare. Det lägger till ett godtyckligt belopp till lat och lon så att du inte kontrollerar alla postnummer i Ohio när du söker efter en radie i Kalifornien. Resten är en del av den tidigare nämnda Great Circle Distance-algoritmen.

Detta kunde förmodligen ha gjorts i en fråga för större effektivitet, men jag behövde det på det här sättet vid den tidpunkten, orsakerna förlorade nu för mig.



  1. Laravel vänster Gå med i den sista posten i höger tabell

  2. SQL SELECT för att få de första N positiva heltalen

  3. grundläggande pyodbc bulkinsats

  4. Vad är skillnaden mellan en temptabell och en tabellvariabel i SQL Server?