PostGIS: assegna l'ID del punto nel livello A al punto più vicino nel livello B


15

Questo avrebbe dovuto essere un ovvio precursore (che non ho fatto) all'altra mia domanda: come creare diagrammi a ragno (linee hub) in PostGIS?

Se non conosco la relazione tra un punto nel livello A (negozi) e un punto nel livello B (clienti), vorrei in generale dire "Il cliente 1 è gestito dal negozio più vicino". Mentre mi rendo conto che questo fatto potrebbe non essere vero, può essere un surrogato decente.

Utilizzando PostGIS, qual è il modo più efficiente per assegnare l'ID del punto più vicino nel livello A (negozi) a ciascun punto nel livello B (clienti). L'output che sto cercando è qualcosa di simile al di sotto.

Customer | Store
    1    |   A
    2    |   A
    3    |   B
    4    |   C

Risposte:


6

allo stesso modo:

seleziona A.ID come CUST_ID, (seleziona B.ID dall'ordine B per st_distance (A.geom, B.geom) limite 1) come STORE_ID da A


Questo è stato il modo migliore per eseguire l'operazione. Vedi la mia nota qui sotto per il codice effettivo che ho usato.
RyanKDalton,

8

Sembra che se hai molti più clienti rispetto ai negozi, potrebbe essere più efficiente creare uno strato di poligoni voronoi per i negozi, quindi unire spazialmente i clienti contro i poligoni del negozio.


1
Mi piace questo approccio!
underdark

Quale approccio sarebbe più semplice per creare poligoni voronoi? Ci sono altre opzioni che ciò che è notato qui: bostongis.com/… bostongis.com/…
RyanKDalton

Penso che il pacchetto di triangolazione e dirichlet di Delaunay nel secondo tutorial sarebbe appropriato, non sono sicuro che sia il più semplice.
Kirk Kuykendall il


5

Da http://www.bostongis.com/?content_name=postgis_nearest_neighbor :

Se è necessario ottenere il vicino più vicino per tutti i record in una tabella, ma è necessario solo il primo vicino più vicino per ciascuno, è possibile utilizzare la sintassi distintiva DISTINCT ON di PostgreSQL. Che sarebbe simile a questo:

SELECT DISTINCT ON(g1.gid)  g1.gid As gref_gid, 
       g1.description As gref_description, 
       g2.gid As gnn_gid, 
       g2.description As gnn_description  
FROM sometable As g1, sometable As g2   
WHERE g1.gid <> g2.gid 
      AND ST_DWithin(g1.the_geom, g2.the_geom, 300)   
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom) 

Questo troverà distanze minime fino a 300 unità. Quindi, devi prima controllare i tuoi dati e scoprire quanto grandi saranno le tue distanze minime.



3

Grazie per il contributo di tutti. Alla fine sono andato con una combinazione di suggerimenti di eprand e underdark. Il codice finale che ho usato era:

CREATE TABLE closest_point as
SELECT DISTINCT ON (A.GID) A.GID AS CUST_ID, 
      (SELECT B.GID FROM "STORES" as B 
       ORDER BY ST_Distance(A.the_geom, B.the_geom) limit 1) as STORE_ID, 
       A.the_geom 
FROM "CUSTOMERS" as A, "STORES" as B;

Ho quindi creato un diagramma voronoi a livello di negozi per confermare che i risultati funzionavano correttamente, cosa che ovviamente hanno fatto. Grazie per l'ottimo lavoro a tutti!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.