sql >> Databasteknik >  >> RDS >> Mysql

Vilket är det bästa sättet att hitta alla adresser som är på ett specifikt avstånd till den valda punkten

När jag har implementerat detta i MySQL (för att lagra platser på en oblate sfär, vilket i princip är vad jorden är (jag antar att du pratar om jorden!)), har jag lagrat så mycket föruträknad information som möjligt i databasen. Så, för en rad som lagrar latitude och longitude , jag beräknar även vid insättningstillfället följande fält:

  • radiansLongitude (Math.toRadians(longitude) )
  • sinRadiansLatitude (Math.sin(Math.toRadians(latitude) )
  • cosRadiansLatitude (Math.cos(Math.toRadians(latitude) )

Sedan när jag söker efter de platser som ligger inom X enheter av latitude /longitude i fråga är mitt förberedda uttalande följande:

from Location l where
    acos(
        sin(:latitude) * sinRadiansLatitude + 
        cos(:latitude) * cosRadiansLatitude * 
        cos(radiansLongitude - :longitude) 
        ) * YYYY < :distance
    and l.latitude>:minimumSearchLatitude
    and l.latitude<:maximumSearchLatitude 
    and l.longitude>:minimumSearchLongitude 
    and l.longitude<:maximumSearchLongitude 
    order by acos(
                sin(:latitude) * sinRadiansLatitude + 
                cos(:latitude) * cosRadiansLatitude * 
                cos(radiansLongitude - :longitude)  
        ) * YYYY asc

Där YYYY =3965 ger dig avstånd i miles eller YYYY =6367 kan användas för avstånd i km.

Slutligen har jag använt maximumSearchLatitude / maximumSearchLongitude / minimumSearchLongitude / maximumSearchLongitude parametrar för att utesluta majoriteten av poängen från resultatuppsättningen innan databasen måste utföra några beräkningar. Du kanske behöver detta eller inte. Om du använder detta är det upp till dig vilka värden du väljer för dessa parametrar, eftersom det beror på vad du söker.

Uppenbarligen kommer det att krävas kloka tillämpningar av index i databasen.

Fördelen med att använda detta tillvägagångssätt är att informationen som aldrig ändras men som behövs varje gång bara beräknas en gång, medan man beräknar värdena för radiansLongitude , sinRadiansLatitude , cosRadiansLatitude för varje rad varje gång du gör en sökning kommer att bli väldigt dyrt väldigt snabbt.

Det andra alternativet är att använda ett geospatialt index , vilket innebär att allt detta hanteras åt dig av databasen. Jag vet dock inte hur bra Hibernate integrerar med det.

Ansvarsfriskrivning:det var länge sedan jag tittade på det här, och jag är ingen GIS-expert!



  1. Konstigt SQLException:Kolumnen hittades inte

  2. Att skicka en array av data som en indataparameter till en Oracle-procedur

  3. Jag försöker en enkel fråga med parametern in med mysql 5.5 genom jdbc-kod

  4. Kontrollera strängens språk baserat på glyfer i PHP