powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Деревья в Postgres
17 сообщений из 17, страница 1 из 1
Деревья в Postgres
    #35916028
coolmiha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть таблица:
Код: plaintext
create table subdiv (ID integer, PARENT integer);
заполняем ее
Код: plaintext
1.
2.
3.
4.
insert into AAA (ID, PARENT) values ( 1 , NULL);
insert into AAA (ID, PARENT) values ( 2 ,  1 );
insert into AAA (ID, PARENT) values ( 3 ,  1 );
insert into AAA (ID, PARENT) values ( 4 ,  2 );
insert into AAA (ID, PARENT) values ( 5 ,  3 );
в итоге будет дерево
1
2 3
4 5
Вопрос такой. Необходимо получить список элементов дерева, находящихся ниже заданной ветки.
Пишу функцию
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create function rec(aid integer) returns SETOF integer as $$
declare
 r integer;
begin
 for r in select id from aaa where parent=aid loop
  IF FOUND THEN
   perform rec(r);
  end if;
  return next r;
 end loop;
end
$$
language 'plpgsql';

Должно получится так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT * FROM rec( 1 );
 rec
-----
 4 
 2 
 5 
 3 
( 4  rows)


Но почему-то функция не хочет уходить в рекурсию и выдает
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from rec( 1 );
 rec
-----
    2 
    3 
( 2  rows)

В чем ошибка?
...
Рейтинг: 0 / 0
Деревья в Postgres
    #35916035
coolmiha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну в смысле
create table AAA (ID integer, PARENT integer);
...
Рейтинг: 0 / 0
Деревья в Postgres
    #35916232
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
coolmihaНо почему-то функция не хочет уходить в рекурсию и выдает
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from rec( 1 );
 rec
-----
    2 
    3 
( 2  rows)

В чем ошибка?ошибка в том, что перформ не возвращает данные в _вашу_ последовательность RETURN-ов
т.ч. вам надо ~
Код: plaintext
1.
2.
3.
4.
IF FOUND THEN
   --perform rec(r);
   for _r in select * FROM rec(r.id)  loop
           RETURN NEXT _r.id
     end if;
...
Рейтинг: 0 / 0
Деревья в Postgres
    #35916375
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуйте connectby из contrib/tablefunc
...
Рейтинг: 0 / 0
Деревья в Postgres
    #35917224
coolmiha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Окончательный вариант
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE OR REPLACE FUNCTION "rec" (_id integer, out _name varchar) RETURNS varchar AS
$body$
DECLARE
    nm varchar;  
    self_id varchar;
    r integer;
BEGIN
    self_id:='';
    FOR r IN SELECT id FROM aaa WHERE parent = _id LOOP  

      self_id = r || ',' || self_id; 
     SELECT rec(r) INTO nm;
      self_id = nm || '' || self_id; 

   END LOOP;
    _name =  self_id;
    RETURN;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
web=# select * from aaa;
 id | parent
----+--------
   1  |
   2  |       1 
   3  |       1 
   4  |       2 
   5  |       3 
   6  |       1 
   7  |       6 
   8  |       6 
   9  |       6 
  10  |       7 
( 10  rows)


Код: plaintext
1.
2.
3.
4.
5.
web=# select rec( 1 );
         rec
---------------------
  9 , 8 , 10 , 7 , 6 , 5 , 3 , 4 , 2 ,
( 1  запись)

Всем спасибо. Решение можно внести в дискурс)
...
Рейтинг: 0 / 0
Деревья в Postgres
    #35918787
Анонимус
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
coolmihaОкончательный вариант
Всем спасибо. Решение можно внести в дискурс)

в 8.4 добавят CTE, там можно будет по-другому делать :)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Деревья в Postgres
    #39350835
fobster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
coolmiha,

как убрать в выводе последнюю запятую и добавить в вывод parent_id?
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39350870
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fobster, вы нашли решение прошлогодней давности
используйте специальный тип данных дерево + расширение для работы с деревьями
деревья
с учетом индексов получите быстрое решение по нахождению любых элементов дерева
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39350907
fobster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka, спасибо за ответ :)
все-таки интересует решение в рамках подобной задачи, когда дерево организовано через id, parent_id
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39351217
SharuPoNemnogu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fobster,

покажите пример исходных данных и результата
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39361134
fobster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
CREATE OR REPLACE FUNCTION accounts.get_group_by_group(
    IN _id uuid,
    OUT _name character varying)
  RETURNS character varying AS
$BODY$
DECLARE
    nm character varying;  
    self_id character varying;
    r uuid;
BEGIN
    self_id:='';
    FOR r IN SELECT id FROM accounts.groups WHERE parent_id = _id LOOP  

      self_id =''''|| r || ''',' || self_id; 
     SELECT accounts.get_group_by_group(r) INTO nm;
      self_id = nm || '' || self_id; 

   END LOOP;
     _name = self_id;   
    RETURN;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION accounts.get_group_by_group(uuid)
  OWNER TO postgres;



SharuPoNemnogu, как в данном запросе вывести не только всех детей, но и родителя?
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39361208
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fobsterкогда дерево организовано через id, parent_id
у мну на рабочей бд аналогично, но классификатор обновлялся не так часто, я через вьюху загнал в формат ltree-)

но у нас и задача была такой, что надо было в одном запросе показать например все листья из группы А, но при этом одновременно выделить отдельно А.А12.А2 и все что в нее входит в отдельную группу товаров. + в эту эе новую группу добавить еще и Q.Q01...

Лучшее способа чем описать все через ltxtquery не нашел) компактные запросы со сложной логикой.
(если таблица изначально так организована, то можно использовать GIN GIST индексы)
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39361215
SharuPoNemnogu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
WITH RECURSIVE r AS (
    WITH tmp AS (
        SELECT * FROM (
                        VALUES
                          ((1), (null)),
                          ((2), (1)),
                          ((3), (1)),
                          ((4), (2)),
                          ((5), (3)),
                          ((6), (1)),
                          ((7), (6)),
                          ((8), (6)),
                          ((9), (6)),
                          ((10), (7))

                      ) AS z (id, parent_id)
    )
    SELECT t.id
    FROM tmp t
    WHERE t.parent_id = 1
    UNION
    SELECT t.id
    FROM tmp t
    INNER JOIN r ON t.parent_id = r.id
)
SELECT string_agg(id::text, ',') FROM r;
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39362742
d3a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SharuPoNemnogu,

От корня
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    with recursive
    "Group" as (
      select G.GroupID, G.ParentID
        from UserGroup G
        where G.ParentID is null
      union all
      select G.GroupID, G.ParentID
        from UserGroup G
        join "Group" on G.ParentID = "Group".GroupID
    )
    select * from "Group" G


Тема раскрыта здесь http://shop.oreilly.com/product/9780596008949.do
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39362914
SharuPoNemnogu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
d3a,

а мне то оно зачем? я повторил пример выше более легким способом, а там суть в том, чтобы от любого элемента построить дерево, а не от корня
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39363372
d3a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SharuPoNemnogu,

Звиняйте, кнопочкой помахнулся - хотел просто в тред запостить.
...
Рейтинг: 0 / 0
Деревья в Postgres
    #39363418
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fobsterLegushka, спасибо за ответ :)
все-таки интересует решение в рамках подобной задачи, когда дерево организовано через id, parent_id

вы, кстати, можете преобразовать ид->парент_ид в ltree представление
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Деревья в Postgres
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]