Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Wyszukiwanie przestrzenne Oracle na odległość

Masz tam całkiem dobre odniesienie do wyszukiwania odległości mySQL.

Zapomnij o rzeczach związanych z Oracle Spatial. Za dużo kodu, za dużo złożoności, za mało wartości dodanej.

Oto zapytanie, które załatwi sprawę. Wykorzystuje odległości w milach ustawowych. EDYTUJ To naprawia błąd wspomniany przez mdarwina, kosztem sprawdzenia dzielenia, jeśli spróbujesz użyć go dla lokalizacji na biegunie północnym lub południowym.

  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

Jeśli pracujesz w kilometrach, zmień mydst/69 na mydst/111.045 i zmień 3959 na 6371.4. (1/69 zamienia mile na stopnie; 3959 to wartość promienia planety).

Teraz prawdopodobnie pokusisz się o użycie tego dużego zapytania jako „magicznej czarnej skrzynki”. Nie rób tego! Nie jest to trudne do zrozumienia, a jeśli to zrozumiesz, będziesz w stanie wykonywać lepszą pracę. Oto, co się dzieje.

Ta klauzula jest sednem tego, co sprawia, że ​​zapytanie jest szybkie. Przeszukuje tabelę Miasta w poszukiwaniu pobliskich miast do określonego punktu.

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

Aby to zadziałało, zdecydowanie potrzebujesz indeksu w kolumnie LATITUDE. Pomocny będzie również indeks w kolumnie LONGITUDE. Wykonuje przybliżone wyszukiwanie, szukając wierszy, które znajdują się w quasi-prostokątnej łacie na powierzchni ziemi w pobliżu twojego punktu. Wybiera zbyt wiele miast, ale niezbyt wiele.

Ta klauzula pozwala wyeliminować dodatkowe miasta z zestawu wyników:

   WHERE distance <= mydst

Ta klauzula to formuła haversine, która oblicza odległość wielkiego koła między każdym miastem a twoim punktem.

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

Ta klauzula umożliwia jednokrotne wprowadzenie punktu i limitu promienia jako zmiennych powiązanych z zapytaniem. Jest to pomocne, ponieważ różne formuły wielokrotnie wykorzystują te zmienne.

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

Reszta zapytania po prostu porządkuje rzeczy, dzięki czemu można wybierać i porządkować według odległości.

Oto pełniejsze wyjaśnienie:http://www.plumislandmedia.net /mysql/haversine-mysql-nearest-loc/



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zgodność HSQLDB ROWNUM z Oracle

  2. Kwerenda scalająca zwracająca ORA-30926:nie można uzyskać stabilnego zestawu wierszy w tabelach źródłowych

  3. Unikalny klucz w Oracle z przykładami

  4. SQL-Statement do użycia predefiniowanej listy wartości jako tabeli SQL

  5. Jaka jest maska ​​formatowania daty Oracle dla stref czasowych?