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

Използвайте MySQL пространствени разширения, за да изберете точки в кръг

В MySQL няма функции за геопространствено разширение, поддържащи изчисления на географска ширина/дължина. Има от MySQL 5.7 .

Искате кръгове за близост на повърхността на земята. Вие споменавате във вашия въпрос, че имате стойности за ширина/дълга за всеки ред във вашите flags таблица, както и универсален напречен Mercator (UTM) прогнозирани стойности в една от няколко различни UTM зони . Ако си спомням правилно моите карти от UK Ordnance Survey, UTM е полезен за намиране на елементи на тези карти.

Лесно е да се изчисли разстоянието между две точки в една и съща зона в UTM:декартовото разстояние върши работа. Но когато точките са в различни зони, това изчисление не работи.

Съответно, за приложението, описано във вашия въпрос, е необходимо да използвате Great Circle Distance , което се изчислява с помощта на хаверсина или друга подходяща формула.

MySQL, допълнен с геопространствени разширения, поддържа начин за представяне на различни равнинни форми (точки, полилинии, многоъгълници и т.н.) като геометрични примитиви. MySQL 5.6 реализира недокументирана функция за разстояние st_distance(p1, p2) . Тази функция обаче връща декартови разстояния. Така че е напълно неподходящ за изчисления на базата на географска ширина и дължина. На умерените ширини степен на географска ширина се простира почти два пъти по-голямо повърхностно разстояние (север-юг) от градус на дължина (изток-запад), тъй като линиите на географска ширина се сближават по-близо до полюсите.

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

Във вашето приложение можете да намерите всички flags точки в рамките на десет законови мили от дадена latpoint,longpoint със заявка като тази:

 SELECT id, coordinates, name, r,
        units * DEGREES(ACOS(LEAST(1.0, COS(RADIANS(latpoint))
                  * COS(RADIANS(latitude))
                  * COS(RADIANS(longpoint) - RADIANS(longitude))
                  + SIN(RADIANS(latpoint))
                  * SIN(RADIANS(latitude))))) AS distance
   FROM flags
   JOIN (
        SELECT 42.81  AS latpoint,  -70.81 AS longpoint, 
               10.0 AS r, 69.0 AS units
        ) AS p ON (1=1)
  WHERE MbrContains(GeomFromText (
        CONCAT('LINESTRING(',
              latpoint-(r/units),' ',
              longpoint-(r /(units* COS(RADIANS(latpoint)))),
              ',', 
              latpoint+(r/units) ,' ',
              longpoint+(r /(units * COS(RADIANS(latpoint)))),
              ')')),  coordinates)

Ако искате да търсите точки в рамките на 20 км, променете този ред на заявката

               20.0 AS r, 69.0 AS units

към това, например

               20.0 AS r, 111.045 AS units

r е радиусът, в който искате да търсите. units са единиците за разстояние (мили, км, фази, каквото искате) на градус на географска ширина на повърхността на земята.

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

И накрая, заявката по-горе избира всички точки в правоъгълника. За да стесните това само до точките в кръга и да ги подредите по близост, увийте заявката по следния начин:

 SELECT id, coordinates, name
   FROM (
         /* the query above, paste it in here */
        ) AS d
  WHERE d.distance <= d.r
  ORDER BY d.distance ASC 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Enum в Hibernate, запазващ се като enum

  2. Кой тип данни на MySQL да използвате за съхранение на булеви стойности

  3. MySQL:множество таблици или една таблица с много колони?

  4. Как да добавя индекси към MySQL таблици?

  5. Създаване на уеб приложение от нулата с помощта на Python Flask и MySQL:Част 4