PostgreSQL рекурсивный родительский / дочерний запрос - PullRequest
0 голосов
/ 27 февраля 2019

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

Вот данные:

                                            Table "public.subjects"
      Column       |            Type             | Collation | Nullable |               Default                
-------------------+-----------------------------+-----------+----------+--------------------------------------
 id                | bigint                      |           | not null | nextval('subjects_id_seq'::regclass)
 name              | character varying           |           |          | 



                                        Table "public.subject_associations"
   Column   |            Type             | Collation | Nullable |                     Default                      
------------+-----------------------------+-----------+----------+--------------------------------------------------
 id         | bigint                      |           | not null | nextval('subject_associations_id_seq'::regclass)
 parent_id  | integer                     |           |          | 
 child_id   | integer                     |           |          | 

Здесь у «субъекта» может быть много родителей и много детей.Конечно, на верхнем уровне у субъекта нет родителей, а на нижнем - детей.Например:

 parent_id  |  child_id  
------------+------------
     2      |     3
     1      |     4
     1      |     3
     4      |     8
     4      |     5
     5      |     6
     6      |     7

Мне нужно начать с child_id, чтобы получить всех предков, а с parent_id - всех потомков.Поэтому:

parent_id 1 -> children 3, 4, 5, 6, 7, 8
parent_id 2 -> children 3

child_id 3 -> parents 1, 2
child_id 4 -> parents 1
child_id 7 -> parents 6, 5, 4, 1

Хотя мне кажется, что есть много примеров подобных вещей, у меня возникают проблемы с их пониманием, поэтому любые предложения, которые я могу попробовать, будут приветствоваться.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019
CREATE OR REPLACE FUNCTION func_finddescendants(start_id integer)
RETURNS SETOF subject_associations
AS $$
DECLARE
BEGIN
    RETURN QUERY
    WITH RECURSIVE t
    AS
    (
        SELECT * 
        FROM subject_associations sa
        WHERE sa.id = start_id
        UNION ALL
        SELECT next.*
        FROM t prev
        JOIN subject_associations next ON (next.parentid = prev.id)
    )
    SELECT * FROM t;
END;
$$  LANGUAGE PLPGSQL;
0 голосов
/ 27 февраля 2019

Чтобы получить всех детей по предмету 1, вы можете использовать

WITH RECURSIVE c AS (
   SELECT 1 AS id
   UNION ALL
   SELECT sa.child_id
   FROM subject_associations AS sa
      JOIN c ON c.id = sa. parent_id
)
SELECT id FROM c;
...