PostGIS - stykające się obiekty

0

Witam

Męczę się od jakiegoś czasu z napisaniem zapytania SQL. Oto opis problemu:
Mam tabelę z trójwymiarowymi poligonami (multipolygon: ogc_fid, group_id, wkb_geometry)
Potrzebuję pogrupować je w grupy stykających się obiektów. Każdemu obiektowi w grupie nadać identyczny numer grupy. Każda z grup musi posiadać unikalny identyfikator.
Niestety funkcja wykonuje się w nieskończoność mimo iż jest tam tylko ok. 20.000 obiektów.

A oto efekt moich wydumań:

CREATE OR REPLACE FUNCTION group_objects() RETURNS boolean AS $$
DECLARE
	_id integer;
    _count integer;
    _value integer := 1;
BEGIN
	LOOP
    	SELECT ogc_fid, COUNT(*) INTO _id, _count FROM multipolygon WHERE group_id IS NULL GROUP BY ogc_fid LIMIT 1;
    	IF _count = 0 THEN RETURN true; END IF;
        UPDATE multipolygon a
            SET group_id = _value
            FROM
                (SELECT wkb_geometry
                 FROM multipolygon
                 WHERE ogc_fid = _id) b
            WHERE ST_Touches(a.wkb_geometry, b.wkb_geometry);
        _value := _value + 1;
    END LOOP;
END; $$
LANGUAGE plpgsql

Z góry dziękuję za pomoc przy napisaniu optymalizacji tego zapytania.

0

Wykonuje się w nieskończoność, bo umieściłeś swoje zapytanie w nieskończonej pętli LOOP ... END LOOP, a nie masz nigdzie jej przerywania EXIT lub EXIT WHEN.

https://www.tutorialspoint.com/plsql/plsql_basic_loop.htm

0

zyxist, dziękuję za szybką odpowiedź. Rzeczywiście jak się nie doczyta to się robi głupoty.

Problem rozwiązany:

CREATE OR REPLACE FUNCTION group_objects() RETURNS void AS $$
DECLARE
	_record RECORD;
	_value  bigint := -1;
	_cursor CURSOR FOR (SELECT ST_Expand(ST_UnaryUnion(sq.grp), 0.05) geom FROM (SELECT unnest(ST_ClusterWithin(wkb_geometry, 0.05)) AS grp FROM public.multipolygon) sq);
BEGIN
	OPEN _cursor;
	LOOP
		_value := _value + 1;
		FETCH _cursor INTO _record;
		EXIT WHEN NOT FOUND;
		INSERT INTO public.analysis (ogc_fid, level, group_id, wkb_geometry)
			(SELECT ogc_fid, level, _value, wkb_geometry FROM public.multipolygon WHERE ST_Covers(_record.geom, wkb_geometry));
	END LOOP;
	CLOSE _cursor;
END; $$
LANGUAGE plpgsql

Nie wiem, czy jest to optymalne rozwiązanie, ale działa...

1 użytkowników online, w tym zalogowanych: 0, gości: 1