Masalah mendapatkan ritsleting dalam radius melalui MySQL

9

Saya memiliki tabel kode pos yang mencakup pusat lat, lng untuk setiap kode pos. Saya menggunakannya untuk mendapatkan daftar kode pos dalam radius mil tertentu dari titik arbitrer.

Baru terpikir oleh saya bahwa, hanya karena titik pusat zip tidak dalam radius yang diberikan, tidak berarti bahwa zip itu sendiri tidak berada dalam radius.

Saya menggunakan keterampilan seni super canggih saya untuk menggambarkan hal ini di sini:

masukkan deskripsi gambar di sini

  • Gumpalan garis-garis hijau mewakili kode pos A, B dan C.

  • Noda merah adalah pusat geografis untuk setiap kode pos

  • Titik fuchsia adalah lokasi target, dan ..

  • Lingkaran biru kental adalah radius 1 mil dari lokasi target

Jika saya menjalankan kueri untuk semua kode pos dalam radius 1 mil dari noda merah muda, hanya kode pos B dan C yang akan dikembalikan karena titik pusat untuk zip A tidak berada dalam radius satu mil, meskipun noda merah muda itu sendiri jelas dalam kode pos A.

SELECT *,
        p.distance_unit
                 * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                 * COS(RADIANS(z.y))
                 * COS(RADIANS(p.longpoint) - RADIANS(z.x))
                 + SIN(RADIANS(p.latpoint))
                 * SIN(RADIANS(z.y)))) AS dist
  FROM standard_zip AS z
  JOIN (   /* these are the query parameters */
        SELECT  $lat  AS latpoint,  $lng AS longpoint,
                $miles AS radius,      69 AS distance_unit
    ) AS p ON 1=1
  WHERE z.y
     BETWEEN p.latpoint  - (p.radius / p.distance_unit)
         AND p.latpoint  + (p.radius / p.distance_unit)
    AND z.x
     BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
         AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
  ORDER BY dist

Bagaimana cara saya menulis kueri yang akan memasukkan zip A dalam hasil?

Saya memiliki akses ke spasial / geometri untuk setiap kode pos yang dapat saya tambahkan ke tabel jika diperlukan, tetapi saya tidak tahu bagaimana saya akan menggunakannya untuk tujuan ini di MySQL.


Sunting : Saya menghabiskan satu hari membaca dokumen Oracle dan MySQL untuk data spasial dan berhasil mengubah data spasial saya menjadi MySQL . Bagaimana cara menulis kueri serupa yang menggunakan kolom geometri, bukan lat dan panjang? Saya menggunakan data 2D .. geometri adalah poligon dan multipoligon saja ..

Saya pikir saya semacam mengatasinya ..

select
  *
from
  (
    select
      MIN(st_distance(geom, POINT(-82.765136, 28.0914015))) * 69 as miles,
      zip
    from
      zip_spatial
    group by
      zip
    order by
      miles asc
  ) d
where
  d.miles < 5

Saya akan membiarkan karunia terbuka untuk saat ini jika seseorang memiliki solusi yang lebih baik, lebih efisien.

Saya pernah bergulat dengan beruang.
sumber

Jawaban:

7

Dari Pengindeksan dan Querying Data Spasial di Oracle dalam Panduan Pengembang Spasial Oracle® 11g Release 2 (11.2):

Meminta Data Spasial

Spasial menggunakan model kueri dua tingkat dengan operasi filter primer dan sekunder untuk menyelesaikan kueri spasial dan gabungan spasial. Istilah dua-tier menunjukkan bahwa dua operasi berbeda dilakukan untuk menyelesaikan kueri. Jika kedua operasi dilakukan, set hasil yang tepat dikembalikan.

Anda tidak bisa menambahkan nama tautan database (dblink) ke nama tabel spasial dalam kueri jika indeks spasial didefinisikan pada tabel itu.

Kueri spasial

Dalam indeks spasial R-tree, setiap geometri diwakili oleh batas minimum persegi panjang (MBR). Pertimbangkan layer berikut yang berisi beberapa objek dalam Gambar1. Setiap objek diberi label dengan nama geometri (geom_1 untuk string baris, geom_2 untuk poligon bersisi empat, geom_3 untuk poligon segitiga, dan geom_4 untuk elips), dan MBR di sekitar setiap objek diwakili oleh garis putus-putus.

Gambar1 Geometri dengan MBR

Deskripsi "Gambar1 Geometri dengan MBR"

Kueri spasial tipikal adalah meminta semua objek yang ada di dalam jendela kueri, yaitu pagar atau jendela yang ditentukan. Jendela permintaan dinamis merujuk ke area persegi panjang yang tidak didefinisikan dalam database, tetapi itu harus ditentukan sebelum digunakan. Gambar 2 menunjukkan geometri yang sama seperti pada Gambar 1, tetapi menambahkan jendela kueri yang diwakili oleh kotak garis putus-putus yang berat.

Gambar2 Lapisan dengan Jendela Kueri

Deskripsi "Gambar2 Lapisan dengan Jendela Kueri"

Pada Gambar 2, jendela kueri mencakup bagian geometri geom_1 dan geom_2, serta bagian MBR untuk geom_3 tetapi tidak ada geometri geom_3 yang sebenarnya. Jendela permintaan tidak mencakup bagian mana pun dari geometri geom_4 atau MBR-nya.

Operator Penyaring Utama

Operator SDO_FILTER, mengimplementasikan bagian filter utama dari proses dua langkah yang terlibat dalam model pemrosesan kueri Oracle Spatial. Filter utama menggunakan data indeks untuk menentukan hanya jika satu set pasangan objek kandidat dapat berinteraksi. Secara khusus, filter utama memeriksa untuk melihat apakah MBR dari objek kandidat berinteraksi, bukan apakah objek itu sendiri berinteraksi. Sintaks operator SDO_FILTER adalah sebagai berikut:

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

Dalam sintaksis sebelumnya:

  • geometry1 adalah kolom tipe SDO_GEOMETRY dalam tabel. Kolom ini harus diindeks spasial.

  • geometry2 adalah objek bertipe SDO_GEOMETRY. Objek ini mungkin atau mungkin tidak berasal dari sebuah tabel. Jika itu berasal dari tabel, itu mungkin atau mungkin tidak diindeks spasial.

  • param adalah string opsional tipe VARCHAR2. Itu dapat menentukan salah satu atau keduanya dari kata kunci min_resolution dan max_resolution.

Contoh-contoh berikut hanya menjalankan operasi filter primer (tanpa operasi filter sekunder). Mereka akan mengembalikan semua geometri yang ditunjukkan pada Gambar2 yang memiliki MBR yang berinteraksi dengan jendela kueri. Hasil dari contoh berikut adalah geometri geom_1, geom_2, dan geom_3.

Contoh1 melakukan operasi filter utama tanpa memasukkan jendela kueri ke dalam tabel. Jendela akan diindeks dalam memori dan kinerja akan sangat baik.

Contoh1 Filter Utama dengan Jendela Permintaan Sementara

SELECT A.Feature_ID FROM TARGET A  WHERE sdo_filter(A.shape, SDO_geometry(2003,NULL,NULL,
                                       SDO_elem_info_array(1,1003,3),
                                       SDO_ordinate_array(x1,y1, x2,y2))
                           ) = 'TRUE';   

Dalam Example1, (x1, y1) dan (x2, y2) adalah sudut kiri bawah dan kanan atas jendela kueri.

llijith
sumber
1
Keren .. Jadi saya harus membuat geometri lingkaran untuk mewakili jari-jari dan kemudian hanya melihat poligon yang bersilangan .. menarik .. thx untuk info
saya bergulat beruang sekali.
Yeah..go on ... Semoga ini bekerja dengan baik untuk Anda.
Ilijith
5

Setiap upaya untuk memasukkan A mungkin akan mencakup D, E, F, G. Masalahnya tidak dapat diselesaikan tanpa memiliki jalur yang tepat mendefinisikan setiap area kode pos.

Temukan basis data seperti itu, lalu buat SPATIALindeks menggunakan poligon yang sewenang-wenang.

Rick James
sumber
Saya tahu saya perlu data spasial (dan saya memilikinya, tetapi ini ada dalam tabel Oracle dan saya tidak menemukan banyak info tentang cara mengubahnya) .. masalahnya adalah mencari tahu bagaimana cara meminta data.
Aku pernah bergulat dengan beruang.
Jika Anda senang dengan kinerja kode baru, itu mungkin yang terbaik. Catatan: Kueri mencantumkan jarak ke setiap zip, jadi mungkin tidak ada potensi optimasi. (Saya akan terkejut jika Anda mendapatkan kode yang lebih baik.)
Rick James
itulah yang saya pikirkan juga. Saya akan memberi Anda hadiah sebelum waktu habis dan Anda mendapatkan setengah dari itu pula .. Hanya ingin melihat apa tanggapan saya yang pertama.
Aku pernah bergulat dengan beruang.
3

Kamu melakukannya dengan salah. Pertama, jika mungkin, gunakan PostGIS - yang merupakan RDMBS terkemuka dengan solusi Spasial.

Maka Anda ingin mengikuti langkah-langkah ini.

  1. Tarik ke bawah ZCTA (Area Tabulasi Kode Pos) dari dataset TIGER Census . Kode pos sebenarnya tidak tahu pasti. Secara resmi, kode pos hanya untuk penggunaan internal oleh USPS. Karena semua orang menggunakannya, termasuk pemerintah, sumber paling otoritatif kedua telah menjadi ZCTA.
  2. Impor shapefile ini ke dalam database Anda, dengan PostgreSQL Anda dapat dengan mudah digunakan shp2pgsql
  3. Buat indeks geometri yang Anda impor.

    CREATE INDEX ON census_zcta USING gist (geog);
    ANALYZE census_zcta;
  4. Jalankan permintaan Point-of-Interest (POI) terhadap shapefile. Tempat menarik dalam kasus Anda adalah Kabel Input, ini akan terlihat seperti ini,

    SELECT *
    FROM census_zcta AS zcta
      WHERE ST_Intersects( zcta, ST_MakePoint(long,lat)::geog );

ℹ 1609.344 Meter = 1 Mil

MySQL

Dengan MySQL, Anda akan memilikinya

  1. Gunakan ogr2ogr untuk mengeluarkan pernyataan penyisipan MySQL untuk Census Shapefile.
  2. Gunakan MBRIntersectsuntuk memanfaatkan indeks spasial. Kueri akhir akan terlihat seperti

    SELECT *
    FROM zcta
    WHERE MBRIntersects( geom, Point(long,lat) )
      AND ST_Intersects ( geom, Point(long,lat) );
Evan Carroll
sumber
3
1) saya tahu saya salah melakukannya. itu sebabnya saya bertanya. 2) perusahaan tempat saya bekerja telah membayar akses ke batas kode pos internal usps. kami bekerja secara langsung dengan usps untuk proyek ini, dan 3) secara umum, menyarankan bahwa OP menggunakan perangkat yang sama sekali berbeda bukanlah jawaban yang tepat.
Aku pernah bergulat dengan beruang.
1
@iwrestledabearonce Anda dapat melakukan semua hal ini dengan MySQL 8 juga cukup ST_DWithindenganMBRIntersects
Evan Carroll
1
"akses berbayar ke usps batas kode pos internal" apakah Anda mengetahui nama produk itu? AFAIK tidak ada hal seperti itu. (meskipun USPS memang menawarkan 2 produk data dan beberapa API untuk alamat decoding)
Evan Carroll
1
terima kasih telah menambahkan info tentang mysql. +1. api tidak umum dan tidak terdaftar di situs mana pun, bahkan url titik akhir bahkan tidak memiliki nama domain, kami memintanya langsung dari alamat ip. namun, hanya untuk membuktikan bahwa api itu ada, tercantum dalam dokumen ini (3 yang merujuk pada EDDM adalah yang saya maksudkan) usps.com/business/web-tools-apis/archive/…
Saya menggulung beruang sekali.
1
Itu sebenarnya tampak sah jika Anda melakukan titik akhir EDDM / SelectZIP. Itu tidak diiklankan untuk tujuan itu, tetapi pujian untuk menemukan titik akhir itu.
Evan Carroll
1

Lihatlah kumpulan data ini dari GreatData.com (perhatikan bahwa ini bukan open source tetapi layanan berbayar).

Mereka menggunakan kepadatan populasi alih-alih pusat zip.

Dan cara menggunakan tipe data spasial server sql untuk mendapatkan hasil yang benar cepat.

Semoga ini membantu.

Matt McDonald
sumber
Apakah kumpulan data ini tersedia untuk MySQL atau hanya untuk SQL Server?
ypercubeᵀᴹ