Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Użyj rozszerzeń przestrzennych MySQL, aby wybrać punkty wewnątrz okręgu

Nie ma funkcji rozszerzeń geoprzestrzennych w MySQL obsługujących obliczenia odległości szerokości i długości geograficznej. Jest od MySQL 5.7 .

Pytasz o kręgi zbliżeniowe na powierzchni ziemi. W swoim pytaniu wspominasz, że masz wartości długości/szerokości dla każdego wiersza w Twoich flags tabeli, a także uniwersalny poprzeczny Mercator (UTM) przewidywane wartości w jednej z kilku różnych strefach UTM . Jeśli dobrze pamiętam moje mapy UK Ordnance Survey, UTM jest przydatny do lokalizowania przedmiotów na tych mapach.

Łatwo jest obliczyć odległość między dwoma punktami w tej samej strefie w UTM:odległość kartezjańska załatwia sprawę. Ale gdy punkty znajdują się w różnych strefach, to obliczenie nie działa.

W związku z tym w przypadku aplikacji opisanej w Twoim pytaniu konieczne jest użycie Great Circle Distance , który jest obliczany za pomocą hasrsine lub innej odpowiedniej formuły.

MySQL, wzbogacony o rozszerzenia geoprzestrzenne, obsługuje sposób przedstawiania różnych płaskich kształtów (punktów, polilinii, wielokątów itd.) jako prymitywów geometrycznych. MySQL 5.6 implementuje nieudokumentowaną funkcję odległości st_distance(p1, p2) . Jednak ta funkcja zwraca odległości kartezjańskie. Więc jest całkowicie nieodpowiednie do obliczeń opartych na szerokości i długości geograficznej. W umiarkowanych szerokościach geograficznych stopień szerokości geograficznej odpowiada prawie dwukrotnie większej odległości powierzchniowej (północ-południe) niż stopniowi długości geograficznej (wschód-zachód), ponieważ linie szerokości geograficznej zbliżają się do siebie bliżej biegunów.

Tak więc formuła bliskości kołowej musi używać prawdziwej szerokości i długości geograficznej.

W swojej aplikacji możesz znaleźć wszystkie flags punkty w promieniu dziesięciu mil statutowych od danego latpoint,longpoint z zapytaniem takim jak to:

 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)

Jeśli chcesz wyszukać punkty w promieniu 20 km, zmień ten wiersz zapytania

               20.0 AS r, 69.0 AS units

do tego, na przykład

               20.0 AS r, 111.045 AS units

r to promień, w którym chcesz szukać. units to jednostki odległości (mile, km, stadia, cokolwiek chcesz) na stopień szerokości geograficznej na powierzchni ziemi.

To zapytanie używa ograniczenia szerokości/długości wraz z MbrContains aby wykluczyć punkty, które są zdecydowanie za daleko od punktu początkowego, użyj wzoru na odległość po wielkim okręgu, aby wygenerować odległości dla pozostałych punktów. wyjaśnienie tego wszystkiego można znaleźć tutaj . Jeśli twoja tabela używa metody dostępu MyISAM i ma indeks przestrzenny, MbrContains wykorzysta ten indeks, aby przyspieszyć wyszukiwanie.

Na koniec powyższe zapytanie wybiera wszystkie punkty w prostokącie. Aby zawęzić to tylko do punktów w okręgu i uporządkować je według odległości, zawiń zapytanie w ten sposób:

 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. Błąd krytyczny:wywołanie funkcji elementu członkowskiego query() na null

  2. SECOND() Przykład – MySQL

  3. Jak wykryć, że transakcja została już rozpoczęta?

  4. Jak zoptymalizować bazę danych witryny

  5. Wiele aktualizacji w MySQL