Postgres: Использование WITH RECURSIVE для создания списка элементов и их родителей - PullRequest
0 голосов
/ 08 мая 2018

У меня есть схема, которая выглядит следующим образом:

CREATE TABLE category (
  id SERIAL PRIMARY KEY,
  parent INTEGER REFERENCES category(id) DEFERRABLE,
  name TEXT NOT NULL UNIQUE );
SET CONSTRAINTS ALL DEFERRED;

Я добавил следующие строки:

INSERT INTO category VALUES (1, NULL, 'animal');
INSERT INTO category VALUES (2, 1, 'dog');
INSERT INTO category VALUES (3, 1, 'cat');
INSERT INTO category VALUES (4, 3, 'siamese');
INSERT INTO category VALUES (5, 3, 'persian');
INSERT INTO category VALUES (6, 7, 'scary1');
INSERT INTO category VALUES (7, 6, 'scary2');

Я пытаюсь выяснить, как рекурсивно запросить это, используя WITH RECURSIVE, чтобы получить результат, который выглядит так:

   ids   |         names      
---------+------------------------
 {1}     | animal
 {2,1}   | dog, animal
 {3,1}   | cat, animal
 {4,3,1} | siamese, cat, animal
 {5,3,1} | persian, cat, animal
 {6,7}   | scary1, scary2
 {7,6}   | scary2, scary1

Где ids - массив, содержащий каждого родителя до корня, а где names - строка, каждое имя которой разделено запятыми. Мне также нужно справиться с парадоксальным состоянием без зависания.

Может ли кто-нибудь указать мне правильное направление?

1 Ответ

0 голосов
/ 08 мая 2018

Из-за циклических зависимостей в ваших данных вы должны проверить, не существует ли id следующей строки, на которую есть ссылки, уже в массиве ids. Используйте distinct on (id) в конечном запросе и выберите строки с наибольшим массивом ids.

with recursive categories as (
    select id, parent, array[id] as ids, name as names
    from category
union all
    select cs.id, c.parent, ids || c.id, concat(names, ', ', name)
    from categories cs
    join category c on cs.parent = c.id
    where c.id <> all(ids)
)
select distinct on (id) ids, names
from categories
order by id, cardinality(ids) desc;

   ids   |        names         
---------+----------------------
 {1}     | animal
 {2,1}   | dog, animal
 {3,1}   | cat, animal
 {4,3,1} | siamese, cat, animal
 {5,3,1} | persian, cat, animal
 {6,7}   | scary1, scary2
 {7,6}   | scary2, scary1
(7 rows)    
...