Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Деревья в Postgres / 17 сообщений из 17, страница 1 из 1
07.04.2009, 09:39
    #35916028
coolmiha
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
Есть таблица:
Код: 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
07.04.2009, 09:41
    #35916035
coolmiha
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
Ну в смысле
create table AAA (ID integer, PARENT integer);
...
Рейтинг: 0 / 0
07.04.2009, 10:35
    #35916232
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
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
07.04.2009, 11:14
    #35916375
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
попробуйте connectby из contrib/tablefunc
...
Рейтинг: 0 / 0
07.04.2009, 14:50
    #35917224
coolmiha
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
Окончательный вариант
Код: 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
08.04.2009, 07:53
    #35918787
Анонимус
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
coolmihaОкончательный вариант
Всем спасибо. Решение можно внести в дискурс)

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

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

покажите пример исходных данных и результата
...
Рейтинг: 0 / 0
06.12.2016, 12:38
    #39361134
fobster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
Код: 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
06.12.2016, 14:06
    #39361208
Legushka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
fobsterкогда дерево организовано через id, parent_id
у мну на рабочей бд аналогично, но классификатор обновлялся не так часто, я через вьюху загнал в формат ltree-)

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

Лучшее способа чем описать все через ltxtquery не нашел) компактные запросы со сложной логикой.
(если таблица изначально так организована, то можно использовать GIN GIST индексы)
...
Рейтинг: 0 / 0
06.12.2016, 14:19
    #39361215
SharuPoNemnogu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
Код: 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
08.12.2016, 16:38
    #39362742
d3a
d3a
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
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
08.12.2016, 19:02
    #39362914
SharuPoNemnogu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Деревья в Postgres
d3a,

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

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

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


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