Tìm hàng xóm gần nhất giữa hai bảng có vị trí điểm trong SpatiaLite?


10

Tôi đã bắt đầu chơi với SpatiaLite ngày hôm nay và đã vấp phải một vấn đề.

Đối với mỗi vị trí điểm được lưu trữ trong bảngOne tôi muốn chọn một điểm, khoảng cách (khoảng cách tuyến tính) gần nhất từ ​​bảngTwo.

Cho đến nay tôi đã đưa ra một giải pháp vụng về sử dụng XEM:

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;

Và sau đó:

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

dường như làm công việc

Hai câu hỏi:

Có cách nào để thực hiện truy vấn đó mà không tạo VIEW không?

Có cách nào khác để tối ưu hóa truy vấn này để có hiệu suất tốt hơn không? Trong một kịch bản thế giới thực, bảng sẽ có hàng trăm nghìn bản ghi và bảngTwo - 1,3 triệu.


Tôi có thể cung cấp cho bạn một cách tiếp cận nhanh hơn vài bậc, nhưng nó sẽ yêu cầu bạn sử dụng chỉ số knngist postgresql 9 thay vì spatialite ...
Ragi Yaser Burhum

thực sự nhanh hơn GRASS, ArcGIS, QGIS, SQLServer và gần như bất kỳ db / Desktop GIS nào khác (chưa thử chức năng láng giềng gần nhất của Oracle) .Just cho tôi biết nếu đó là một tùy chọn.
Ragi Yaser Burhum

@Ragi: Tôi biết rằng PostGIS sẽ là cách hiệu quả hơn để làm việc với vấn đề như vậy. Tuy nhiên, mục tiêu cuối cùng của bài tập này là tạo ra một ứng dụng di động nhỏ và trong trường hợp này SpatiaLite là người chiến thắng.
radek

Nền tảng phát triển của bạn cho ứng dụng di động của bạn là gì?
Allan Adair

@ ALLan: Hiện đang hoạt động trên cả hai: Windows Server 2008 & Ubuntu.
radek

Câu trả lời:


5

Tôi vừa kiểm tra SQL này và nó hoạt động:

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

Như bạn có thể đọc ở đây "Cách ngây thơ để thực hiện truy vấn hàng xóm gần nhất là sắp xếp bảng ứng viên theo khoảng cách từ hình dạng truy vấn, sau đó lấy bản ghi với khoảng cách nhỏ nhất".

Trân trọng,

Andrea


Tôi đang cố gắng sử dụng truy vấn này nhưng tôi nhận được kết quả không mong muốn - Tôi đang nhận được bảng kết quả nhưng với ID cho các dòng tôi có thể thấy không phải là hàng xóm gần nhất. Tôi đang cố gắng tìm dòng gần nhất trong lớp chuỗi đa dòng đến từng điểm trong lớp khác. Tôi mới với spatiaLite. Bất kỳ đề xuất? Ngoài ra, cuối cùng tôi muốn chạy nó trên 1 triệu + điểm
kflaw

Tôi cũng không chắc là tôi hiểu mục đích của tuyên bố này: WHERE g1.OGC_FID <> g2.OGC_FID
kflaw 19/07/2015

Ngoài ra, trong kết quả của tôi, tôi nhận được khoảng cách null. Tôi đã chơi xung quanh với dòng này: AND ST_Contains (ST_Expand (g1.geometry, 50), g2.geometry) cũng như xóa nó và vẫn không nhận được giá trị khoảng cách, mặc dù tôi đang nhận được ID
kflaw 19/07/2015

6

Nếu bạn không muốn tính khoảng cách giữa tất cả các kết hợp điểm, bạn có thể sử dụng chỉ số không gian trên một trong các bảng:

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

Tôi đã thử sử dụng giải pháp bạn đã đăng khi tôi cần sử dụng chỉ mục không gian, nhưng nó không trả về giá trị? đối với dòng f_table_name = 'A', tôi có cần thay 'A' bằng tên bảng thực tế (bảng một) không? Tôi đã thử một trong hai cách và nó vẫn không trả lại bất cứ điều gì, tại sao điều này có thể xảy ra
kflaw 29/07/2015

Bạn đúng f_table_name = 'A'nên f_table_name = 'tableOne'. Lưu ý rằng yêu cầu này giả định spatialite> 4.x ( SpatialIndexbảng ảo được sử dụng). Bạn đã cố gắng để điều chỉnh search_framecho trường hợp sử dụng của bạn? Trong ví dụ trên, các điểm được cho là ở khoảng cách tối đa 10000 mét.
Samuel

Tôi đã chơi xung quanh với giá trị khung tìm kiếm, tôi cho rằng điều đó có nghĩa là trong vòng 10000 mét sẽ phù hợp với tôi. Tôi thực sự không biết phiên bản nào của spatialite, tôi đã tạo cơ sở dữ liệu thông qua qgis và đang sử dụng gui trong qgis. Hãy để tôi xem nếu tôi có thể tìm ra điều đó
kflaw

Đó là phiên bản 4.1.1 với phiên bản sqlite 3.7.17, vậy nó có hoạt động không? Tôi tự hỏi có gì sai tôi sẽ kiểm tra thêm một chút
kflaw

3

Do phiên bản 4.4.0 SpatiaLite hỗ trợ chỉ mục bảng ảo KNN cho các vấn đề lân cận gần nhất. Dưới đây là một truy vấn tìm thấy dòng gần nhất trong bảng linestring đến từng điểm trong bảng điểm.

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

2

Bạn có thể đơn giản hóa truy vấn của bạn như thế này.

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

Đối với một giải pháp chung chung hơn, có thể đáng để thử chuyển đổi chức năng Hàng xóm gần nhất của PostGIS này: http://blog.mackerron.com/2011/03/postgis-gầnest-neighbour /


Thật không may, mã này dẫn đến:SQL error: "misuse of aggregate: MIN()"
radek

Kể từ PostGIS cũng có một số ví dụ trên trang web BostonGIS, nhưng cho đến nay tôi đã không thành công trong việc dịch chúng sang SpatiaLite: /
radek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.