SpatiaLite'da nokta konumları olan iki tablo arasında en yakın komşuları mı buluyorsunuz?


10

Bugün SpatiaLite ile oynamaya başladım ve zaten bir sorunla karşılaştım.

TableOne içinde saklanan her nokta konumu için tableTwo öğesinden bir, en yakın (doğrusal mesafe) noktayı seçmek istiyorum.

Şimdiye kadar VIEW kullanan beceriksiz bir çözüm buldum:

CREATE VIEW testview AS 
SELECT 
A.id , 
B.myValue, 
Distance(A.Geometry, B.Geometry) AS distance
FROM tableOne AS A, tableTwo AS B
WHERE distance < 10000
ORDER BY A.Id, distance;

Ve sonra:

SELECT * FROM testview
WHERE distance = (SELECT MIN(distance) FROM testview AS t WHERE t.id = testview.id)

işi yapıyor gibi görünüyor.

İki soru:

GÖRÜNÜM oluşturmadan böyle bir sorgu yapmanın bir yolu var mı?

Bu sorguyu daha iyi performans için optimize etmenin başka bir yolu var mı? Gerçek bir dünya senaryosunda tableOne'da yüzlerce çift binlerce kayıt ve tableTwo - 1.3 milyon olacak.


Size daha hızlı birkaç büyüklük sırası olan bir yaklaşım verebilirim, ancak spatialite yerine postgresql 9 knngist endeksi kullanmanızı gerektirir ...
Ragi Yaser Burhum

aslında GRASS, ArcGIS, QGIS, SQLServer ve hemen hemen diğer tüm uzamsal db / Masaüstü GIS'den daha hızlı (Oracle'a en yakın komşu işlevselliğini denemedim) .Sadece bir seçenek olup olmadığını bana bildirin.
Ragi Yaser Burhum

@Ragi: PostGIS'in böyle bir problemle çalışmanın çok daha verimli bir yolu olacağını biliyorum. Bununla birlikte, bu egzersizin nihai amacı küçük taşınabilir bir uygulama yapmak olacaktır ve bu durumda SpatiaLite kazanır.
radek

Taşınabilir uygulamanız için geliştirme platformunuz nedir?
Allan Adair

@Allan: İkisi üzerinde çalışıyor: Şu anda Windows Server 2008 ve Ubuntu.
radek

Yanıtlar:


5

Ben sadece bu SQL test ve çalışıyor:

SELECT g1.OGC_FID As id1, g2.OGC_FID As id2, MIN(ST_Distance(g1.GEOMETRY,g2.GEOMETRY)) AS DIST
FROM table_01 As g1, table_02 As g2   
WHERE g1.OGC_FID <> g2.OGC_FID
AND ST_Contains(ST_Expand(g1.geometry,50),g2.geometry)
GROUP BY id1
ORDER BY id1

Okumak gibi burada "en yakın komşu sorgu yürütmek için naif bir yol sorgu geometri mesafeye göre aday tablosunu sipariş ve sonra en küçük mesafe ile rekor almaktır".

Saygılarımla,

Andrea


Bu sorguyu kullanmaya çalışıyorum ama beklenmedik sonuçlar alıyorum - sonuçta elde edilen bir tablo alıyorum ama görebileceğiniz satırlar için kimlikleri ile en yakın komşu değildir. Başka bir katmanda her noktaya çok satırlı bir dize katmanındaki en yakın satırı bulmaya çalışıyorum. SpatiaLite ile yeniyim. Herhangi bir öneri? Ayrıca, sonuçta bunu 1 milyon + puanda çalıştırmak istiyorum
kflaw

Ayrıca bu ifadenin amacını anladığımdan da emin değilim: WHERE g1.OGC_FID <> g2.OGC_FID
kflaw

Ayrıca, sonuçta boş mesafe alıyorum. Bu çizgiyle oynadım: AND ST_Contains (ST_Expand (g1.geometry, 50), g2.geometry) yanı sıra kaldırdım ve bir kimlik alıyorum bile hala mesafe değerleri
almıyorum

6

Tüm nokta kombinasyonları arasındaki mesafeleri hesaplamak istemiyorsanız, tablolardan birinde uzamsal bir dizin kullanabilirsiniz:

SELECT 
  A.id , 
  B.myValue, 
  MIN(Distance(A.Geometry, B.Geometry)) AS distance
FROM tableOne AS A, tableTwo AS B
WHERE A.ROWID IN (
  SELECT ROWID
  FROM SpatialIndex WHERE
    f_table_name = 'A' 
    AND search_frame = BuildCircleMbr(ST_X(B.Geometry), ST_Y(B.Geometry), 10000))
GROUP BY A.id, B.myValue

Uzamsal bir dizin kullanmam gerektiği için yayınladığınız çözümü kullanmaya çalıştım, ancak değer döndürmedi mi? satır için f_table_name = 'A', 'A' yerine gerçek tablo adını (tablo 1) koymam gerekir mi? Her iki şekilde de denedim ve hala hiçbir şey döndürmüyor, neden bu olabilir
kflaw

Haklı f_table_name = 'A'olmalısın f_table_name = 'tableOne'. Bu isteğin spatialite> 4.x olduğunu varsayar ( SpatialIndexsanal tablo kullanılır). search_frameKullanım durumunuz için ayarlamayı denediniz mi? Yukarıdaki örnekte, noktaların en fazla 10000 metre olduğu varsayılmaktadır.
Samuel

Arama kare değeri ile oynadım, bunun 10000 metre içinde benim için çalışması gerektiğini düşünüyorum. Aslında hangi spatialite sürümünü bilmiyorum, qgis aracılığıyla veritabanı oluşturdum ve qgis gui kullanıyorum. Bakalım bunu anlayabilir
miyim

Bu sqlite 3.7.17 sürüm 4.1.1, bu yüzden o zaman çalışması gerekir? Yanlış olanı merak ediyorum biraz daha test
edeceğim

3

4.4.0 sürümünden beri SpatiaLite en yakın komşu sorunları için bir KNN sanal tablo dizinini desteklemektedir. Burada bir linestring tablosundaki bir nokta tablosundaki her noktaya en yakın çizgiyi bulur.

SELECT k.* FROM knn k, points p
WHERE f_table_name = 'linestrings' 
AND ref_geometry = p.geometry
AND max_items = 1;

2

Sorgunuzu bu şekilde basitleştirebilirsiniz.

SELECT 
   A.id , 
   B.myValue, 
   MIN(Distance(A.Geometry, B.Geometry)) AS distance
FROM tableOne AS A, tableTwo AS B
GROUP BY A.id, B.myValue

Daha genel bir çözüm için, bu PostGIS En Yakın Komşu işlevini dönüştürmeye çalışmak yararlı olabilir: http://blog.mackerron.com/2011/03/postgis-nearest-neighbour/


ne yazık ki kod sonuçları:SQL error: "misuse of aggregate: MIN()"
radek

PostGIS'den itibaren BostonGIS web sitesinde bazı örnekler de var , ancak şu ana kadar onları SpatiaLite'ye çevirmede başarılı olamadım: /
radek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.