У меня есть база данных PostgreSQL 9.1, в которой хранится несколько «областей» с границами, и мне нужно определить эффективную границу для области. Некоторые области хранят границу непосредственно (как геометрия PostGIS), тогда как другие состоят из нескольких дочерних областей, которые необходимо объединить вместе.
Для каждого дочернего элемента существует «операция», которая определяет, будет ли он добавлен к предыдущему или вычтен из него или пересекается с ним. Это означает, что порядок также имеет значение, поэтому есть порядковый номер.
У меня есть агрегатная функция, которая решает эту проблему, но проблема в том, что структура является рекурсивной - дочерняя область сама может состоять из дочерних областей.
Упрощенная схема:
CREATE TABLE area
(id integer NOT NULL
, border geometry NULL
);
CREATE TABLE area_part
(parent_area_id integer NOT NULL
, sequence integer NOT NULL
, operation text NOT NULL
, child_area_id integer NOT NULL
);
Сигнатура агрегированной функции (она ожидает строки, упорядоченные по sequence
):
CREATE AGGREGATE aggregate_geometry(area geometry, operation text)
-- RETURNS geometry
Я создал обычную функцию PL / pgSQL, которая вызывает себя рекурсивно и работает, но медленно, потому что выполняет много подзапросов. Любые идеи о том, как это можно сделать более эффективно?
Я также пытался написать запрос с рекурсивным CTE:
WITH RECURSIVE area_rec AS
(
SELECT *
FROM area
WHERE id = the_if_of_interest
UNION ALL
SELECT c.*
FROM area_rec rec
JOIN area_part p ON rec.id = p.parent_area_id
JOIN area c ON p.child_area_id = c.id
)
SELECT *
FROM area_rec
Это хорошо для возврата всех строк, необходимых для данной области, но я не знаю, как затем вставить значения в мою статистическую функцию. Мне нужна какая-то «совокупная рекурсивная функция» здесь!