Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle пространствено търсене на разстояние

Имате доста добра справка там за mySQL търсене от разстояние.

Забравете за нещата на Oracle Spatial. Твърде много код, твърде много сложност, недостатъчна добавена стойност.

Ето една заявка, която ще свърши работа. Това използва разстояния в статутни мили. РЕДАКТИРАНЕ Това коригира грешката, спомената от mdarwin, с цената на проверка на разделяне, ако се опитате да го използвате за местоположение на северния или южния полюс.

  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
 

Ако работите в километри, променете mydst/69 на mydst/111.045 и променете 3959 на 6371.4. (1/69 преобразува мили в градуси; 3959 е стойност за радиуса на планетата.)

Сега вероятно ще се изкушите да използвате тази голяма заявка като „магическа черна кутия“. Не го прави! Не е много трудно за разбиране и ако го разберете, ще можете да вършите по-добра работа. Ето какво се случва.

Тази клауза е сърцето на това, което прави заявката бърза. Той търси в таблицата ви с градове градове в близост до точката, която сте посочили.

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

За да работи, определено се нуждаете от индекс във вашата колона LATITUDE. Индекс във вашата колона LONGITUDE също ще помогне малко. Той прави приблизително търсене, като търси редове, които са в рамките на квази-правоъгълен участък на повърхността на земята близо до вашата точка. Той избира твърде много градове, но не твърде много.

Тази клауза тук ви позволява да елиминирате допълнителните градове от вашия набор от резултати:

   WHERE distance <= mydst
 

Тази клауза е формулата за хаверсинус, която изчислява разстоянието по големия кръг между всеки град и вашата точка.

<предварителен (3959 * ACOS(COS(RADIANS(LATITUDE)) * COS(RADIANS(mylat)) * COS(RADIANS(LONGITUDE) - RADIANS(mylng)) + SIN(RADIANS(LATITUDE)) * SIN(RADIANS(mylat))

Тази клауза ви позволява да въведете вашата точка и вашата граница на радиуса само веднъж като обвързани променливи към вашата заявка. Полезно е, защото различните формули използват тези променливи многократно.

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

Останалата част от заявката просто организира нещата, така че да избирате и подреждате по разстояние.

Ето по-пълно обяснение: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. Как да създадете чужд ключ в Oracle SQL Developer?

  2. Как да използвате Distributed AD, за да намалите времето за корекция в Oracle EBS

  3. как да изпълните множество заявки за oracle c#

  4. Oracle SQL - max() с NULL стойности

  5. Oracle - Как да принудите потребителя да ВМЪКНЕ няколко реда