Восхождение на отношения между родителями и детьми в Postgres - PullRequest
6 голосов
/ 04 февраля 2009

У нас есть следующая таблица примеров (фактически взятая из другого примера здесь на stackoverflow ...)

CREATE TABLE example (
  id integer primary key,
  name char(200),
  parentid integer,
  value integer);

И, учитывая конкретного ребенка, мы хотим получить лучшего Родителя.

Мне известна функция соединения с помощью функции tablefunc, но она предназначена для получения детьми родителей.

Но меня интересует другое направление, учитывая ребенка, каков его главный родитель? Какой тип запроса я бы попытался использовать?

Любой дружеский совет приветствуется.

Ответы [ 5 ]

4 голосов
/ 04 февраля 2009

Просмотрите книги Джо Селко, SQL для умников и его книгу Деревья и иерархии . У него есть один или два раздела в SQL для Smarties по деревьям и иерархиям, или, если вы действительно хотите в него разобраться, вы можете получить другую книгу. SQL for Smarties также затронет множество других вопросов, касающихся дизайна базы данных и запросов. Там есть действительно хорошие вещи. Он представляет альтернативные способы моделирования деревьев, которые могут работать гораздо лучше, чем используемая вами модель списка смежности.

В одной из его моделей вопрос о том, кто является самым верхним из родителей, становится очень тривиальным.

1 голос
/ 06 апреля 2009

С рекурсивной версией PostgreSQL 8.4 и выше?

1 голос
/ 05 февраля 2009

Вы можете использовать "ltree" contrib модуль.

1 голос
/ 04 февраля 2009

Вы можете написать функцию PL / PgSQL для выполнения рекурсии:

CREATE LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION get_top_parent(
        child integer
) RETURNS integer as $$
DECLARE
        parent integer;
        last_parent integer;
BEGIN
        last_parent := child;
        SELECT INTO parent parentid
        FROM example
        WHERE id = child;

        IF parent is NOT NULL THEN
                parent := get_top_parent(parent);
        ELSE
                parent := last_parent;
        END IF;
        RETURN parent;
END
$$ LANGUAGE plpgsql;

Эта функция определенно может быть оптимизирована. Вероятно, он будет медленным, если глубина очень велика, а таблицы большие, поэтому, как упомянул Джегерн, возможно, стоило бы кэшировать иерархию, возможно, используя триггеры и тому подобное.

0 голосов
/ 04 февраля 2009

По моему опыту, SQL не очень хорош в такого рода запросах (рекурсия). Я бы предложил создать дополнительную таблицу с идентификатором и идентификатором верхнего родительского элемента. Когда вы добавляете больше дочерних элементов, вы просто просматриваете идентификатор родительского элемента его родителя и вставляете соответствующую строку в дополнительную таблицу.

Вы также можете сохранить идентификатор родительского элемента в исходной таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...