ค้นหาเพื่อนบ้านที่ใกล้ที่สุดระหว่างสองตารางที่มีตำแหน่งจุดใน SpatiaLite หรือไม่


10

ฉันเริ่มเล่นกับ SpatiaLite วันนี้และพบปัญหาแล้ว

สำหรับตำแหน่งของจุดแต่ละจุดที่เก็บไว้ในตารางฉันต้องการเลือกหนึ่งจุดที่ใกล้ที่สุด (ระยะทางเชิงเส้น) จาก tableTwo

จนถึงตอนนี้ฉันคิดวิธีแก้ปัญหาแบบเงอะงะที่ใช้ประโยชน์จาก VIEW:

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;

แล้ว:

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

ดูเหมือนว่าจะทำงาน

สองคำถาม:

มีวิธีในการดำเนินการค้นหาโดยไม่สร้าง VIEW หรือไม่

มีวิธีอื่นในการเพิ่มประสิทธิภาพการค้นหานี้เพื่อประสิทธิภาพที่ดีขึ้นหรือไม่ ในตารางสถานการณ์ในโลกแห่งความจริงหนึ่งจะมีบันทึกนับร้อยนับพันคู่และตารางสอง - 1.3 ล้าน


ฉันสามารถให้วิธีการที่มีขนาดของคำสั่งได้เร็วขึ้น แต่คุณจะต้องใช้ดัชนี postgresql 9 knngist แทน spatialite ...
Ragi Yaser Burhum

จริงเร็วกว่า GRASS, ArcGIS, QGIS, SQLServer และอื่น ๆ อีกมากมายที่เกี่ยวกับอวกาศ / เดสก์ท็อป GIS (ยังไม่ได้ลองใช้ฟังก์ชั่นเพื่อนบ้านที่ใกล้ที่สุดของ Oracle) เพียงแค่บอกให้ฉันรู้ว่ามันเป็นตัวเลือก
Ragi Yaser Burhum

@Ragi: ฉันทราบว่า PostGIS จะเป็นวิธีที่มีประสิทธิภาพมากขึ้นในการทำงานกับปัญหาดังกล่าว อย่างไรก็ตามเป้าหมายสูงสุดของแบบฝึกหัดนี้คือการสร้างแอพพกพาขนาดเล็กและในกรณีนี้ SpatiaLite เป็นผู้ชนะ
radek

แพลตฟอร์มการพัฒนาสำหรับแอปพกพาของคุณคืออะไร
Allan Adair

@Allan: ทำงานได้ทั้ง: Windows Server 2008 และ Ubuntu ในขณะนี้
radek

คำตอบ:


5

ฉันเพิ่งทดสอบ SQL นี้และใช้งานได้:

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

ในขณะที่คุณสามารถอ่านได้ที่นี่ "วิธีที่ไร้เดียงสาในการดำเนินการแบบสอบถามเพื่อนบ้านที่ใกล้ที่สุดคือการสั่งซื้อตารางผู้สมัครตามระยะทางจากรูปทรงเรขาคณิตของแบบสอบถามแล้วจึงบันทึกด้วยระยะทางที่น้อยที่สุด"

ขอแสดงความนับถืออย่างสูง,

อันเดรีย


ฉันกำลังพยายามใช้การค้นหานี้ แต่ฉันได้รับผลลัพธ์ที่ไม่คาดคิด - ฉันกำลังรับตารางผลลัพธ์ แต่ด้วย ID สำหรับบรรทัดที่ฉันเห็นไม่เพื่อนบ้านที่ใกล้ที่สุด ฉันพยายามค้นหาบรรทัดที่ใกล้ที่สุดในเลเยอร์สตริงหลายบรรทัดไปยังแต่ละจุดในเลเยอร์อื่น ฉันใหม่กับ spatiaLite ข้อเสนอแนะใด ๆ นอกจากนี้ในที่สุดฉันก็ต้องการรันสิ่งนี้บนคะแนน 1 ล้านคะแนน
kflaw

ฉันยังไม่แน่ใจว่าฉันเข้าใจวัตถุประสงค์ของคำชี้แจงนี้: WHERE g1.OGC_FID <> g2.OGC_FID
kflaw

นอกจากนี้ในผลของฉันฉันได้รับระยะห่างเป็นโมฆะ ฉันได้เล่นกับบรรทัดนี้: และ ST_Contains (ST_ ขยาย (g1.geometry, 50), g2.geometry) รวมทั้งลบออกและยังไม่ได้รับค่าระยะทางแม้ว่าฉันจะได้รับ ID
kflaw

6

หากคุณไม่ต้องการคำนวณระยะทางระหว่างชุดค่าผสมทั้งหมดคุณสามารถใช้ดัชนีปริภูมิบนหนึ่งในตาราง:

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

ฉันพยายามใช้วิธีแก้ปัญหาที่คุณโพสต์เนื่องจากฉันต้องการใช้ดัชนีเชิงพื้นที่ แต่ไม่คืนค่าหรือไม่ สำหรับบรรทัดf_table_name = 'A'ฉันต้องแทนที่ 'A' ด้วยชื่อตารางจริง (ตารางที่หนึ่ง) หรือไม่ ฉันพยายามอย่างใดอย่างหนึ่งและมันก็ยังไม่กลับมาอะไรเลยสิ่งนี้อาจจะเป็น
kflaw

คุณมีสิทธิที่ควรจะเป็นf_table_name = 'A' f_table_name = 'tableOne'โปรดทราบว่าคำขอนี้จะถือว่ามีการทำ spatialite> 4.x (ใช้SpatialIndexตารางเสมือนจริง) คุณพยายามปรับเปลี่ยนsearch_frameกรณีการใช้งานของคุณหรือไม่? ในตัวอย่างข้างต้นจะถือว่าคะแนนอยู่ในระยะทางสูงสุด 10,000 เมตร
ซามูเอล

ฉันเล่นด้วยค่าเฟรมค้นหาฉันคิดว่านั่นหมายความว่าภายในระยะ 10,000 เมตรซึ่งน่าจะเหมาะกับฉัน จริง ๆ แล้วฉันไม่รู้ว่า spatialite รุ่นใดฉันสร้างฐานข้อมูลผ่าน qgis และฉันใช้ gui ใน qgis ขอผมดูหน่อยว่าผมจะหาได้
ไหม

มันเป็นเวอร์ชั่น 4.1.1 กับ sqlite เวอร์ชั่น 3.7.17 ดังนั้นมันควรจะทำงานเหรอ? ฉันสงสัยว่ามีอะไรผิดปกติฉันจะทดสอบเพิ่มเติมอีก
kflaw

3

ตั้งแต่เวอร์ชัน 4.4.0 SpatiaLite สนับสนุนดัชนีตารางเสมือน KNN สำหรับปัญหาเพื่อนบ้านที่ใกล้ที่สุด นี่คือแบบสอบถามการค้นหาบรรทัดที่ใกล้ที่สุดในตารางการคืนค่าแต่ละจุดในตารางจุด

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

2

คุณสามารถทำให้แบบสอบถามของคุณง่ายขึ้นเช่นนี้

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

สำหรับวิธีแก้ปัญหาทั่วไปที่มากขึ้นมันอาจคุ้มค่าที่จะลองใช้ฟังก์ชั่น PostGIS ใกล้เคียงที่สุดที่ใกล้เคียงที่สุด: http://blog.mackerron.com/2011/03/postgis-nearest-neighbour/


น่าเสียดายที่โค้ดส่งผลให้:SQL error: "misuse of aggregate: MIN()"
radek

ในฐานะของ PostGIS ยังมีบางตัวอย่างในเว็บไซต์ BostonGIS แต่จนถึงขณะนี้ฉันยังไม่ประสบความสำเร็จในการแปลพวกเขาเป็น SpatiaLite: /
radek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.