sql >> Database teknologi >  >> RDS >> Mysql

Find alle postnumre inden for angivet afstand fra et postnummer

Her er noget, jeg skrev for et stykke tid siden, som måske kan starte dig i den rigtige retning.

Mens du bad om VB.Net, har du virkelig brug for en forespørgsel, der laver en "Great Circle Afstand " beregning for at bestemme afstanden mellem to punkter identificeret ved breddegrad og længdegrad.

Så gør følgende antagelser:

  1. Dine postnummerdata er i en enkelt tabel.
  2. Tabellen har attributter for lat og lon, der er det omtrentlige tyngdepunkt for postnummeret

Du kan bruge en LINQ til SQL-forespørgsel, der producerer det ønskede resultatsæt ved at bruge noget som dette

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 kompliceret ud, for det er det. Der er langt klogere folk her på SO, der kan forklare algoritmen. Jeg implementerede blot dette fra noget SQL-kode, jeg fandt på internettet - jeg kan ikke huske hvorfra. En Google-søgning burde bringe dig derhen.

Den første forespørgsel (zipQry) returnerer lat og lon for startpostnummeret i både grader og radianer. Disse resultater bruges derefter til at udføre den anden forespørgsel.

Den første del af WHERE-sætningen i den anden forespørgsel:

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 lige indsnævret listen over postnumre, der skal undersøges, hvilket får forespørgslen til at køre meget hurtigere. Det tilføjer et vilkårligt beløb til lat og lon, så du ikke tjekker alle postnumre i Ohio, når du søger efter en radius i Californien. Resten er alt sammen en del af den førnævnte Great Circle Distance-algoritme.

Dette kunne sandsynligvis have været gjort i én forespørgsel for større effektivitet, men jeg havde brug for det på denne måde på det tidspunkt, årsagerne er nu gået tabt for mig.



  1. Omdøbning af kolonner i en SQL SELECT-sætning

  2. hvordan man kalder MySQL lagret procedure i spring boot ved hjælp af dvale?

  3. Forespørgselstimeout i pg-promise

  4. Byg et bord under runtime i Ruby on Rails