Vì vậy, ví dụ. Đây là một bảng đơn giản với hai nhóm cạnh được kết nối:
drop table lines;
create table lines ( id integer primary key, geom geometry(linestring) );
insert into lines (id, geom) values ( 1, 'LINESTRING(0 0, 0 1)');
insert into lines (id, geom) values ( 2, 'LINESTRING(0 1, 1 1)');
insert into lines (id, geom) values ( 3, 'LINESTRING(1 1, 1 2)');
insert into lines (id, geom) values ( 4, 'LINESTRING(1 2, 2 2)');
insert into lines (id, geom) values ( 11, 'LINESTRING(10 10, 10 11)');
insert into lines (id, geom) values ( 12, 'LINESTRING(10 11, 11 11)');
insert into lines (id, geom) values ( 13, 'LINESTRING(11 11, 11 12)');
insert into lines (id, geom) values ( 14, 'LINESTRING(11 12, 12 12)');
create index lines_gix on lines using gist(geom);
Bây giờ, đây là một hàm đệ quy, với id của một cạnh, tích lũy tất cả các cạnh chạm vào:
CREATE OR REPLACE FUNCTION find_connected(integer) returns integer[] AS
$$
WITH RECURSIVE lines_r AS (
SELECT ARRAY[id] AS idlist, geom, id
FROM lines
WHERE id = $1
UNION ALL
SELECT array_append(lines_r.idlist, lines.id) AS idlist,
lines.geom AS geom,
lines.id AS id
FROM lines, lines_r
WHERE ST_Touches(lines.geom, lines_r.geom)
AND NOT lines_r.idlist @> ARRAY[lines.id]
)
SELECT
array_agg(id) AS idlist
FROM lines_r
$$
LANGUAGE 'sql';
Điều đó chỉ khiến chúng ta cần tìm, sau khi mỗi nhóm được tích lũy, id của một cạnh chưa phải là một phần của một nhóm. Mà, bi thảm thay, đòi hỏi một truy vấn đệ quy thứ hai.
WITH RECURSIVE groups_r AS (
(SELECT find_connected(id) AS idlist,
find_connected(id) AS grouplist,
id FROM lines WHERE id = 1)
UNION ALL
(SELECT array_cat(groups_r.idlist,find_connected(lines.id)) AS idlist,
find_connected(lines.id) AS grouplist,
lines.id
FROM lines, groups_r
WHERE NOT idlist @> ARRAY[lines.id]
LIMIT 1)
)
SELECT id, grouplist
FROM groups_r;
Mà kết hợp lại trả về một tập hợp đẹp với id hạt giống và mỗi nhóm nó tích lũy. Tôi để nó như một bài tập cho người đọc để biến các mảng id trở lại thành một truy vấn để tạo hình học cho ánh xạ.
id | grouplist
----+---------------
1 | {1,2,3,4}
11 | {11,12,13,14}
(2 rows)