powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Рекурсивный перебор
13 сообщений из 13, страница 1 из 1
Рекурсивный перебор
    #35322163
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как сделать рекурсивную функцию возвращающую путь по дереву до элемента.
id - номер элемента, id_parent - номер родителя.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE OR REPLACE FUNCTION GetPath(in_id integer)
RETURNS integer AS $$
DECLARE id_p integer;
BEGIN
  if in_id >  0  then
     select id_parent
     into id_p
     from doc_tree
     where id=in_id;
     RETURN id_p;
     select GetPath(in_P);
  end if;  
END;
$$ LANGUAGE 'plpgsql';
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322251
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут как я понимаю проблема в том, что функция может возвратить одно значение.
Процедур в PG нет.
Как быть?
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322389
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322460
Kruchinin Pahan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Youra PolishukТут как я понимаю проблема в том, что функция может возвратить одно значение.
Процедур в PG нет.
Как быть?
1. Возвращай массив. INT4[], например.
2. Для этой задачи не нужна рекурсия, так как в этой задаче не нужен стек.
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322708
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот переделанный пример. У меня не работает.
При вызове select GetPath(4);
Пишет ошибку:
ERROR: set-valued function called in context that cannot accept a set
КОНТЕКСТ: PL/pgSQL function "getpath" line 5 at RETURN NEXT

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
CREATE OR REPLACE FUNCTION GetPath(integer)
RETURNS setof integer AS $$
DECLARE id_p integer;
BEGIN
  id_p = $ 1 ;
  LOOP
    RETURN NEXT id_p;
    SELECT id_parent INTO id_p from doc_tree where id = id_p;
    IF id_p =  0  OR NOT FOUND THEN
       EXIT;
    END IF;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE 'plpgsql';
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322735
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Youra PolishukВот переделанный пример. У меня не работает.
При вызове select GetPath(4);
Пишет ошибку:
ERROR: set-valued function called in context that cannot accept a set
КОНТЕКСТ: PL/pgSQL function "getpath" line 5 at RETURN NEXTselect * from getpath(4);
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322791
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заработало.
Спасибо.
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35322984
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как поставить ограничение при выборке всех id дерева.
Передаю в функцию id вершины дерева. Мне нужно вернуть все элементы этого дерева.
Не понимаю почему, но не срабатывает условие выхода из цикла
IF id = 0 OR NOT FOUND THEN!

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
CREATE OR REPLACE FUNCTION GetTree(integer)
RETURNS setof integer AS $$
DECLARE id integer;
BEGIN
  id = $ 1 ;
  LOOP
    RETURN NEXT id;
    SELECT id INTO id from doc_tree where id_parent = id;
    IF id =  0  OR NOT FOUND THEN
       EXIT;
    END IF;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE 'plpgsql';
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35323221
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Youra PolishukКак поставить ограничение при выборке всех id дерева.
Передаю в функцию id вершины дерева. Мне нужно вернуть все элементы этого дерева.
Не понимаю почему, но не срабатывает условие выхода из цикла
IF id = 0 OR NOT FOUND THEN!

Код: plaintext
SELECT id INTO id from doc_tree where id_parent = id;
если я не путаю, запрос в PLPGSQL SELECT INTO должен возвращать одну строку. то есть для прохода последовательно по предкам (на каждом уровне по одному) такой способ работает, а вот для потомков (на каждом уровне может быть больше одного) надо как-то по-другому. вот например рекурсивный вариант (из рабочей программы)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
create or replace function url_tree( integer, integer ) returns setof url_inf1 as '
    DECLARE
    this_rec RECORD;
    chld_rec RECORD;
    next_rec RECORD;

    BEGIN
    select into this_rec $2 as url_id;
    RETURN NEXT this_rec;

    FOR chld_rec IN select url_id from urls where site_id = $1 and referer = ( select url from urls where url_id = $2 ) and url_depth > ( select url_depth from urls where url_id = $2 ) order by url_id LOOP
        FOR next_rec IN select url_id from url_tree($1,chld_rec.url_id) LOOP
            RETURN NEXT next_rec;
        END LOOP;
    END LOOP;

    RETURN;
    END;
' language 'plpgsql';
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35323315
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот такая функция работает.
Можно как-то задать row_id1 типа integer? Мне не нужена вся строка. Достаточно только id.
Что можно в этой функции подправить?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE OR REPLACE FUNCTION GetTree(integer)
RETURNS setof integer AS $$
DECLARE row_id1 doc_tree%ROWTYPE;
DECLARE row_id2 doc_tree%ROWTYPE;
BEGIN
  FOR row_id1 IN SELECT * from doc_tree where id_parent = $ 1  LOOP
   RETURN NEXT row_id1.id;  
   FOR row_id2 IN SELECT * from GetTree(row_id1.id) LOOP
    RETURN NEXT row_id2.id;  
   END LOOP;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE 'plpgsql';
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35323717
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может быть сделать ineteger вместо doc_tree%ROWTYPE, SELECT id вместо SELECT * и row_id1 вместо row_id1.id?
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35324900
Youra Polishuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Понял.
Когда я таким образом запускаю функцию. Как мне объявить, что возвращается поле с названием
id?
Код: plaintext
select * from GetTree( 2 );
Чтобы можно было сделать вот так
Код: plaintext
1.
2.
select g.id ,d.name
from GetTree( 2 ) g, doc_tree d
where g.id = d.id;
...
Рейтинг: 0 / 0
Рекурсивный перебор
    #35325478
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
например так select * from GetTree(2) id, doc_tree d where id.id = d.id;
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Рекурсивный перебор
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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