Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Gunakan ekstensi spasial MySQL untuk memilih titik di dalam lingkaran

Tidak ada fungsi ekstensi geospasial di MySQL yang mendukung perhitungan jarak lintang/bujur. Ada pada MySQL 5.7 .

Anda meminta lingkaran kedekatan di permukaan bumi. Anda menyebutkan dalam pertanyaan Anda bahwa Anda memiliki nilai lintang/bujur untuk setiap baris di flags tabel, dan juga merkator transversal universal (UTM) memproyeksikan nilai di salah satu dari beberapa zona UTM yang berbeda . Jika saya mengingat peta UK Ordnance Survey saya dengan benar, UTM berguna untuk menemukan item di peta tersebut.

Ini masalah sederhana untuk menghitung jarak antara dua titik di zona yang sama di UTM:jarak Cartesian berhasil. Namun, ketika titik berada di zona yang berbeda, perhitungan itu tidak akan berhasil.

Oleh karena itu, untuk aplikasi yang dijelaskan dalam pertanyaan Anda, perlu menggunakan Jarak Lingkaran Besar , yang dihitung menggunakan haversine atau formula lain yang sesuai.

MySQL, ditambah dengan ekstensi geospasial, mendukung cara untuk mewakili berbagai bentuk planar (titik, polyline, poligon, dan sebagainya) sebagai primitif geometris. MySQL 5.6 mengimplementasikan fungsi jarak tidak terdokumentasi st_distance(p1, p2) . Namun, fungsi ini mengembalikan jarak Cartesian. Jadi itu sama sekali tidak cocok untuk perhitungan berdasarkan garis lintang dan garis bujur. Pada garis lintang sedang, satu derajat garis lintang menunjukkan jarak permukaan hampir dua kali lipat (utara-selatan) dibandingkan dengan derajat garis bujur (timur-barat), karena garis lintang tumbuh lebih dekat bersama-sama di dekat kutub.

Jadi, rumus kedekatan melingkar perlu menggunakan garis lintang dan garis bujur asli.

Dalam aplikasi Anda, Anda dapat menemukan semua flags poin dalam jarak sepuluh mil undang-undang dari latpoint,longpoint yang diberikan dengan pertanyaan seperti ini:

 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)

Jika Anda ingin mencari titik dalam jarak 20 km, ubah baris kueri ini

               20.0 AS r, 69.0 AS units

untuk ini, misalnya

               20.0 AS r, 111.045 AS units

r adalah radius di mana Anda ingin mencari. units adalah satuan jarak (mil, km, furlong, apa pun yang Anda inginkan) per derajat garis lintang di permukaan bumi.

Kueri ini menggunakan garis lintang/bujur pembatas bersama dengan MbrContains untuk mengecualikan titik yang pasti terlalu jauh dari titik awal Anda, maka gunakan rumus jarak lingkaran besar untuk menghasilkan jarak untuk titik yang tersisa. penjelasan tentang semua ini dapat ditemukan di sini . Jika tabel Anda menggunakan metode akses MyISAM dan memiliki indeks spasial, MbrContains akan mengeksploitasi indeks itu untuk membuat Anda mencari dengan cepat.

Akhirnya, kueri di atas memilih semua titik di dalam persegi panjang. Untuk mempersempitnya menjadi hanya titik-titik dalam lingkaran, dan mengurutkannya berdasarkan kedekatan, bungkus kueri seperti ini:

 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. MySQL -- Menggabungkan Antar Basis Data Pada Server Berbeda Menggunakan Python?

  2. Bagaimana menghubungkan ke Sumber Data MySQL di Visual Studio

  3. Bagaimana cara MEMESAN DENGAN SUM () di MySQL?

  4. Bagaimana Fungsi RTRIM() Bekerja di MySQL

  5. ROW_NUMBER() di MySQL