2011-12-20 3 views
1

Есть ли простой способ выбрать корневой узел поддерева (PostgreSQL ltree) из запроса, который возвращает (потенциально) несколько узлов-потомков того же поддерева ? Я выполнил довольно подробный алгоритм для достижения задачи (~ 40 строк, отступов и отформатированных), но было бы здорово, если бы я мог использовать тот факт, что данные на основе данных являются фактически деревьями и имеют легкодоступный корневой узел. Важно отметить, что несколько отдельных корней поддерева могут быть возвращены из одного запроса, поэтому я не могу просто сортировать данные и захватывать верхний результат.Выбор корневого узла из запроса поддерева (PostgreSQL ltree), который возвращает несколько потомков

07 июня 2012 г. Я обновил запрос до последней версии, которая сокращает временную сложность пополам. Он использует самоподдерживающееся (если хотите) удаление всех узлов из поддерева, у которых есть предки в поддереве.

По сути, мой алгоритм работает следующим образом:

WITH roots AS 
(
    /* Place any query here, which returns a field "ancestry" of type ltree */ 
) 
SELECT roots.* 
    FROM roots 
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM roots AS ancestors 
    WHERE ancestors.ancestry @> roots.ancestry 
    AND ancestors.id <> roots.id 
); 

(для получения более подробной информации, пожалуйста, смотрите мою суть, здесь: https://gist.github.com/1507368)

+0

Я использую версию 9.1.2 – Dylon

+0

Ваш вопрос противоречив. Вы хотите определить (один) корневой узел, утверждая, что существует «несколько, разных корней поддерева». И в то же время? –

+0

Это не противоречит, см. Мой сущность, здесь: https://gist.github.com/1507368 – Dylon

ответ

1

Разве вы не можете просто использовать функцию подпуть()?

SELECT 
    SUBPATH(ancestry, 0, 1) 
FROM 
    some_table; 
+0

Нет, возьмите эту иерархию, например: 1 <- 2 <- 3 <- 4 <- 5, где 2 наследует от 1, 3 наследует от 2 и т. Д. Здесь 1 является корневым узлом дерева. Теперь предположим, что согласно предикату для JOIN выше, поддерево, возвращаемое из запроса, таково: 3 <- 4 <- 5 (исключая узлы 1 и 2). Если бы я использовал функцию SUBPATH, она вернула бы 1, когда мне нужно было вернуть 3. Это было хорошее предложение. Благодаря! – Dylon

+0

Тогда я не получу его ... если что-то вернет путь «3.4.5», оценка подпути («3.4.5», 0, 1) даст вам 3. Можете ли вы предоставить некоторую структуру выборки и образец данные для этих двух таблиц, а также результат выборки, который вы хотите получить? Обратите внимание на возможность использования nlevel (ancestry) в сочетании с subpath(). –

+0

Если родословная узла 5 действительно была «3.4.5», тогда это сработало бы, но ее родословная «1.2.3.4.5», для которой SUBPATH (ancestry, 0, 1) вернет 1, а не 3. I Я создал сущность, здесь: https://gist.github.com/1507368 – Dylon