PostGIS: Przypisz identyfikator punktu w warstwie A do najbliższego punktu w warstwie B

15

To powinno być oczywistym prekursorem (którego nie zadałem) mojego drugiego pytania: jak tworzyć diagramy pająków (linie piasty) w PostGIS?

Jeśli nie znam związku między punktem w warstwie A (sklepy) a punktem w warstwie B (klienci), ogólnie chciałbym powiedzieć: „Klient 1 jest obsługiwany przez najbliższy sklep”. Chociaż zdaję sobie sprawę, że ten fakt może nie być prawdą, może być przyzwoitym surogatem.

Za pomocą PostGIS, jaki jest najbardziej efektywny sposób przypisania identyfikatora najbliższego punktu w warstwie A (sklepy) do każdego punktu w warstwie B (klienci). Wynik, którego szukam, jest podobny do poniższego.

Customer | Store
    1    |   A
    2    |   A
    3    |   B
    4    |   C
RyanKDalton
źródło

Odpowiedzi:

6

również:

wybierz A.ID jako CUST_ID, (wybierz B.ID z zamówienia B według st_distance (A.geom, B.geom) limit 1) jako STORE_ID z A

eprand
źródło
To był najlepszy sposób na wykonanie zadania. Zobacz moją notatkę poniżej, aby zobaczyć rzeczywisty kod, którego użyłem.
RyanKDalton,
8

Wygląda na to, że jeśli masz dużo więcej klientów niż masz sklepy, bardziej efektywne może być utworzenie warstwy wielokątów voronoi dla sklepów, a następnie połączenie przestrzenne klientów z wielokątami sklepu.

Kirk Kuykendall
źródło
1
Podoba mi się to podejście!
podmrok
Które podejście byłoby najłatwiejsze do stworzenia polis voronoi? Czy istnieją inne opcje, o których tu mowa : bostongis.com/… bostongis.com/…
RyanKDalton
Myślę, że pakiet Triangulacji i Dirichleta Delaunaya w drugim samouczku byłby odpowiedni, nie jestem jednak pewien, czy jest najłatwiejszy.
Kirk Kuykendall
5

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

Jeśli potrzebujesz uzyskać najbliższego sąsiada dla wszystkich rekordów w tabeli, ale potrzebujesz tylko pierwszego najbliższego sąsiada dla każdego, możesz użyć charakterystycznej składni DISTINCT ON dla PostgreSQL. Który wyglądałby mniej więcej tak:

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) 

Znajdzie to minimalne odległości do 300 jednostek. Musisz więc najpierw sprawdzić swoje dane i dowiedzieć się, jak duże będą Twoje minimalne odległości.

podmrok
źródło
3

Dzięki za wkład wszystkich. Ostatecznie wybrałem kombinację sugestii eprand i podmroku. Ostateczny kod, którego użyłem to:

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;

Następnie utworzyłem diagram voronoi na warstwie sklepów, aby potwierdzić, że wyniki działały poprawnie, co oczywiście zrobiły. Dzięki za wspaniałą pracę wszystkim!

RyanKDalton
źródło