sql >> Database >  >> RDS >> Mysql

Vind alle postcodes binnen de opgegeven afstand van een postcode

Hier is iets dat ik een tijdje geleden heb geschreven en dat je misschien in de juiste richting kan sturen.

Terwijl je om VB.Net vroeg, heb je echt een query nodig die een "Great Circle doet Afstand " berekening om de afstand te bepalen tussen twee punten geïdentificeerd door breedte- en lengtegraad.

Dus de volgende veronderstellingen maken:

  1. Uw postcodegegevens staan ​​in één tabel.
  2. Genoemde tabel heeft attributen voor lat en lon die bij benadering het zwaartepunt van de postcode zijn

Je zou een LINQ naar SQL-query kunnen gebruiken die de gewenste resultatenset produceert met zoiets als dit

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

Het ziet er ingewikkeld uit, want dat is het ook. Er zijn veel slimmere mensen hier op SO die het algoritme kunnen verklaren. Ik heb dit alleen geïmplementeerd vanuit een SQL-code die ik op internet vond - ik kan me niet herinneren waar. Een Google-zoekopdracht zou je daar moeten brengen.

De eerste query (zipQry) retourneert de lat en lon van de beginnende postcode in zowel graden als radialen. Deze resultaten worden vervolgens gebruikt om de tweede zoekopdracht uit te voeren.

Het eerste deel van de WHERE-component in de tweede query:

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

Ik heb zojuist de lijst met te onderzoeken postcodes verkleind, waardoor de zoekopdracht veel sneller verloopt. Het voegt een willekeurig bedrag toe aan de lat en lon, zodat u niet alle postcodes in Ohio controleert wanneer u naar een straal in Californië zoekt. De rest maakt allemaal deel uit van het eerder genoemde Great Circle Distance-algoritme.

Dit had waarschijnlijk in één zoekopdracht kunnen worden gedaan voor meer efficiëntie, maar ik had het destijds op deze manier nodig, de redenen zijn nu voor mij verloren.



  1. Een kapotte SQL-weergave herstellen

  2. Hoe FROM_DAYS() werkt in MariaDB

  3. Probleem met het uitvoeren van de procedure in het spring bootschema.sql-bestand

  4. MySQL - case-statement optimaliseren