-
как избавиться от with recursive в запросе:
BEGIN
RETURN query
WITH RECURSIVE R AS
(SELECT id
FROM accounts.groups WHERE id=(_id)
UNION ALL
SELECT accounts.groups.id
FROM accounts.groups
JOIN R
ON accounts.groups.parent_id = r.id
)
SELECT *FROM R;
END;
-
Уточните пожалуйста, вы хотите тот же результат, не используя WITH RECURSIVE ?
-
именно так.
-
быстрее без введения дополнительных полей никак. А вот если поле добавить текстовое и заполнять его таким образом: 1. родитель 1.1. - 1 потомок 1 уровня 1.2. - 2 потомок 1 уровня 1.1.1. - 1 потомок 2 уровня То получить список потомков по родителю select * from table where hierarchy like '1.%' Ну, а дальше на сколько фантазии хватит.
-
изменение структуры таблицы не планировалось . иерархия у нас организована с помощью полей id, parent_id. можно ли организовать функцию с выводом дерева с помощью цикла?
-
да. А чем with recursive не устраивает? У вас будет входящий Id родителя чтобы получить потомков или нужно все дерево?
-
Если все дерево, то 1. Перед циклом наполняете временную таблицу temp записями из своей table 2. В цикле объединяете вновь добавленные записи таблицы temp со своей таблицей и результат вставляете опять в temp и так пока объединяется.
-
Если входящий Id, то в п.1. наполняем не всеми записями, а только отобранной по id
-
можно ли организовать функцию с выводом дерева с помощью цикла?
тебе какая разница где будет рекурсия, в постгрессе или в цикле?
это к тому, что придумав иерархическую организацию данных, надо юзать рекурсию по полной, а не спрашивать как от нее избавиться.
-
как будет выглядеть подобный запрос в цикле?
-
он будет выглядеть как корова обутая в седло
-
мне нужна корова :) почему этот вариант возвращает только вершину дерева? CREATE OR REPLACE FUNCTION accounts.without_recursive(_id uuid) RETURNS table (id uuid, parent_id uuid, name character varying(64))AS
$BODY$
DECLARE
r uuid;
BEGIN
--return query
FOR r in SELECT id, parent_id, name FROM accounts.groups WHERE id = _id
LOOP
return query
select ag.id, ag.parent_id, ag.name from accounts.groups as ag join r ON ag.id = r.parent_id;
RETURN NEXT;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' STABLE STRICT
-
ну iop, раскоментарь первый ретурн. пропала и сама вершина?
и какой вывод?
-
хорошо, я поняла. тема названа не верно. нужно было написать не 'как избавиться от рекурсии' а как можно по-другому запросить данные.
> iop
а вот что не так с ретурнами я не догоняю.
-
если после раскоментаренного первого ретурна пропадает вершина иерархии, то это значит, что когда он закоментарен, то ты вылетаешь из цикла по ретурну на первой же итерации. и в выборке только вершина дерева.
-
Че-то я не понял, в чем проблема с with recursive ? К сожалению синтаксиса postgresql я не знаю. Но по ходу 1 что увидел, Вам нужно объединять вновь добавленные записи а не все. т.е. на 1 итерации все, допустим от 1...100, на второй уже от 101 до 120.
-
если в базе сделать логическую ошибку, то используя в запросе with recursive можно повесить базу. этот код выбирает родителя и первую ветку детей, остальное не выводит. почему??? CREATE OR REPLACE FUNCTION accounts.without_recursive(_id uuid) RETURNS table (id uuid, parent_id uuid, name character varying(64))AS
$BODY$
DECLARE
row_ record;
BEGIN
RETURN query
--возвращаем первую ветку дерева
SELECT us.id, us.parent_id, us.name FROM accounts.groups us WHERE us.id = _id;
--возвращаем детей
FOR row_ IN SELECT us.id, us.parent_id, us.name FROM accounts.groups us WHERE us.id = _id
LOOP
RETURN query
SELECT r.id, r.parent_id, r.name FROM accounts.groups AS r WHERE r.parent_id =row_.id;
RETURN NEXT;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
-
короче. без рекурсии у тебя ничего не получится. даже если однажды из этой функции вылезет вторая ветка детей. но так как рекурсией можно повесить вашу кривую иерархию,
то вывод простой
спиливать дерево и клепать плоские таблицы заточенные на N поколений вложенности. не больше.
-
хотя если дерево на id + parent_id то как его можно зациклить?
простой вариант когда id = parent_id
других вроде нет, а этот вычищается на раз.
-
kate158 © (12.10.16 17:14) [16] Ничего не понимаю, а где временная таблица?
-
kate158, прочитайте внимательно stas © (11.10.16 15:19) [5]
-
стасик, зачем ей читать твоё пять, если тебе русским языком написали, что дерево кривое, и рекурсивный запрос на ихней иерархии зацикливается.
вот тем и не устраивает.
-
iop © (12.10.16 19:21) [21] Тоже верно. Точнее stas © (11.10.16 15:22) [6]. Можно конечно в цикле поставить максимальный уровень вложенности, допустим 100. Но это закопать проблему еще глубже.
iop © (12.10.16 17:49) [18] Есть еще вариант: id=1, parentId=3 id=2, parentId=1 id = 3 parentId=2
-
> iop © (12.10.16 19:21) [21]
чем дерево кривое? на хабре полно статей про такую структуру дерева, где parent_id=id id=1 parent_id=пусто id=2 parent_id=1 id=3 parent_id=1 id=4 parent_id=2 id=5 parent_id=2 сейчас ничего не зацикливается, но в случае логической ошибки может. так сказали наши программисты. я с этим не сталкивалась, не знаю. но мой запрос завернули :)
-
kate158 © (13.10.16 11:14) [23] А не проще сделать check на логическую ошибку при записи?
-
чем дерево кривое? на хабре полно статей про такую структуру дерева, где parent_id=id
корнет, вы женщина?
-
kate158 © Вы наверное все таки напишите запрос, чтобы понять как работает рекурсивное дерево.
-
iop © (13.10.16 11:28) [25] я в этом не виновата :)
-
> stas © (13.10.16 11:31) [26]
stas © (13.10.16 11:31) [26]with t as(
SELECT id, parent_id, name
FROM accounts.groups b WHERE id='7e8a97b0-7353-11e6-84f9-2314e71f8a19'
union all
select a.id, a.parent_id, a.name
from accounts.groups as a
inner join b on b.parent_id = a.id)
select * from t ?
-
kate158 © (14.10.16 16:07) [28] Имел ввиду, доделайте тот,что начали ).
|