sql >> Database teknologi >  >> RDS >> Oracle

Oracle rumlig søgning inden for afstand

Du har en ret god reference der til mySQL-afstandssøgning.

Glem alt om Oracle Spatial-tingene. For meget kode, for meget kompleksitet, ikke nok værditilvækst.

Her er en forespørgsel, der vil gøre tricket. Dette bruger afstande i statut miles. REDIGER Dette retter fejlen nævnt af mdarwin, på bekostning af divide-checking, hvis du prøver at bruge den til en placering på nord- eller sydpolen.

SELECT id, city, LATITUDE, LONGITUDE, distance FROM ( SELECT id, city, LATITUDE, LONGITUDE, (3959 * ACOS(COS(RADIANS(LATITUDE)) * COS(RADIANS(mylat)) * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) + SIN(RADIANS(LATITUDE)) * SIN(RADIANS(mylat)) )) AS distance, b.mydst FROM Cities JOIN ( SELECT :LAT AS mylat, :LONG AS mylng, :RADIUS_LIMIT AS mydst FROM DUAL )b ON (1 = 1) WHERE LATITUDE >= mylat -(mydst/69) AND LATITUDE <= mylat +(mydst/69) AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat)))) AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat)))) )a WHERE distance <= mydst ORDER BY distance

Hvis du arbejder i kilometer, skal du ændre mydst/69 til mydst/111.045 og ændre 3959 til 6371.4. (1/69 konverterer miles til grader; 3959 er en værdi for planetens radius.)

Nu vil du sandsynligvis blive fristet til at bruge denne store forespørgsel som en "magisk sort boks." Gør det ikke! Det er ikke særlig svært at forstå, og hvis du forstår det, vil du være i stand til at gøre et bedre stykke arbejde. Her er, hvad der sker.

Denne klausul er kernen i det, der gør forespørgslen hurtig. Den søger i tabellen Byer for nærliggende byer til det punkt, du har angivet.

     WHERE LATITUDE >=  mylat -(mydst/69)
       AND LATITUDE <=  mylat +(mydst/69)
       AND LONGITUDE >= mylng -(mydst/(69 * COS(RADIANS(mylat))))
       AND LONGITUDE <= mylng +(mydst/(69 * COS(RADIANS(mylat))))
 

For at det kan fungere, skal du helt sikkert have et indeks på din LATITUDE-kolonne. Et indeks på din LONGITUDE kolonne vil også hjælpe lidt. Den udfører en omtrentlig søgning og leder efter rækker, der er inden for en kvasi-rektangulær plet på jordens overflade nær dit punkt. Den udvælger for mange byer, men ikke alt for mange.

Denne klausul her lader dig fjerne de ekstra byer fra dit resultatsæt:

   WHERE distance <= mydst
 

Denne klausul er haversineformlen, som beregner afstanden mellem storcirklerne mellem hver by og dit punkt.

(3959 * ACOS(COS(RADIANS(LATITUDE)) * COS(RADIANS(mylat)) * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) + SIN(RADIANS(LATITUDE)) * SIN(RADIANS(mylat))

Denne klausul lader dig indtaste dit punkt og din radius-grænse én gang som bundne variabler til din forespørgsel. Det er nyttigt, fordi de forskellige formler bruger disse variable flere gange.

        SELECT :LAT AS mylat,
               :LONG AS mylng,
               :RADIUS_LIMIT AS mydst
          FROM DUAL
 

Resten af ​​forespørgslen organiserer simpelthen tingene, så du vælger og bestiller efter afstand.

Her er en mere komplet forklaring:http://www.plumislandmedia.net /mysql/haversine-mysql-nearest-loc/



  1. Sådan får du vist, hvilken Postgres-version der kører

  2. Kopiering af emojis i tekst fra MySQL til SQL Server

  3. Hvordan bruger man ilike sqlalchemy på postgresql array felt?

  4. MySQL ALTER TABLE på meget stort bord - er det sikkert at køre det?