Иерархические отношения PostgreSQL - PullRequest
1 голос
/ 26 июня 2011
CREATE TABLE sectors
(
    sector_id integer PRIMARY KEY,
    sector_name varchar(100) NOT NULL,
    parent_sector_id integer REFERENCES sectors(sector_id)
);

INSERT INTO sectors(sector_id, sector_name, parent_sector_id)
SELECT 1, 'All sectors', NULL UNION ALL
SELECT 2, 'Business', 1 UNION ALL
SELECT 3, 'Manufacturing', 2 UNION ALL
SELECT 4, 'Retail', 2 UNION ALL
SELECT 5, 'Trading', 1 UNION ALL
SELECT 6, 'Nonprofit', 1 UNION ALL
SELECT 7, 'Agriculture', 1;

Вопрос 1: Найти родительские отношения с помощью функции

SELECT is_parent(1/*All sectors*/, 4/*Retail*/) should be true
SELECT is_parent(2/*Business*/, 4/*Retail*/) should be true

Вопрос 2: Найти дочерние отношения с помощью функции

SELECT is_child(4/*Retail*/, 1/*All sectors*/) should be true
SELECT is_child(4/*Retail*/, 2/*Business*/) should be true

Любая помощь по этому вопросу будет принята с благодарностью.

Ответы [ 2 ]

3 голосов
/ 26 июня 2011

Если вам действительно нужно ответить на такие запросы, я бы порекомендовал вам взглянуть на Рекурсивные запросы PostgreSQL .Если это какая-то домашняя работа, когда вам нужно написать эти функции (is_parent, is_child), я бы также порекомендовал вам реализовать их с помощью рекурсивных запросов.

2 голосов
/ 27 июня 2011

Добавление к ответу Пабло ...

Используя рекурсивные запросы, is_parent() будет очень быстрым.Предполагая, что у вас есть индекс на parent_sector_id, вы будете в основном делать одно сканирование индекса на уровень глубины.

is_child(), напротив, будет очень медленным, если вы реализуете его наивным образом иу вас есть огромное дерево, иначе не захватывать все дочерние элементы и проверять ваш узел.

Если у вас есть такое дерево и иногда требуется получить все дочерние элементы, один хороший вариант - реализовать предварительно упорядоченное деревоалгоритм (с использованием чисел с плавающей точкой или чисел; не целых чисел, поскольку они чрезвычайно замедляют запись) или вложенные интервалы.

Если нет, просто измените аргументы и вызовите is_parent(), то есть функция sql is_child(a, b) вернет is_parent(b, a).

И последнее, но не менее важное, вы можете захотеть взглянуть на тип данных ltree в contrib.Используя его, вы можете выполнять запросы is_parent / is_child с индексом gist на произвольных узлах.

...