"Tonal" wrote ...
24.06.2011 13:49, Khorsun Vlad пишет:
EB вполне устраивает.
   Он не будет рекурсивным.
Этому есть какие-то причины теоретического плана или технического?

   Нет конечно, это мой каприз.

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

Видимо я ошибался. Но до сих пор не понимаю причину нежелания делать рекурсию в 
ЕБ.
Возможно это как-то связано с мониторингом или другими подобными механизмами.
Поэтому и хочется узнать причины из первых рук.
Расскажи в общих чертах.

   Да, ошибался. В общих чертах - EB сделан на уровне DSQL, который стоит "над"
движком, который выполняет запросы. Поэтому для самого движка нет такого 
понятия,
как EB. И возможность рекурсивного вызова туда так просто не приделать.

Да, вобщем-то можно просто ввести опциональное имя для ЕБ.
Тогда нет нужды в каком-то дополнительном ключевом слове. :)

   Не в имени дело.

По факту единственным универсальным инструментом для работы с деревьями
на сервере остаются рекурсивные сохранёнки. :(
   Не вижу в этом ничего плохого. Ну и это утверждение ничем не доказано.

Вот я и пытаюсь это обосновать.

   Что именно ? Что нет ничего плохого в процедурах ? :)

Про удаление мы вроде бы выяснили:
delete from ... where id in (with recursive...)
отвалится, если связь без каскадного удаления, т. к. невозможно задать
порядок удаления.
   Нет, мы выяснили что есть for with recursive который позволяет не
писать процедуру (А ЧЕМ ПЛОХО ПИСАТЬ ПРОЦЕДУРУ ???)и обойтись без
несуществующего рекурсивного EB

Т. е. без применения PL-SQL не обойтись. Согласен.

   EB это тоже PSQL, как ни странно. (Кстати PL\SQL - это из оракла, у нас PSQL)

Хотя на мой взгляд какой-то вариант delete был бы более ясныйм и простым 
способом...

   Ясность и простота - понятия часто субъективные...

Нельзя сделать поиск по путям.

   Ты с кем разговариваешь ? Я тебя уже потерял :)

Это когда узел идентифицируется не его ID-ом а последовательностью
значений какого-то атрибута по уровням (как путь в файловой системе)

   А в чём проблема ? И зачем для такой схемы рекурсия ?

Опять же, такой запрос как посчитать количество дочек для каждого узла в
указанной ветке будет отставать по скорости примерно на степень от
прямой рекурсивной реализации (как O(n) от O(n^2) или больше).

   Опять бездоказательное утверждение. И опять не вижу причин отказываться
от процедур.

Для простейшего дерева выдать количество непосредственных детей
действительно проблем нет:
...
Но вот подсчитать количество всех детей у меня не вышло. :(
...
Кто предложит рабочий вариант подсчёта общего количества прямых и
непрямых детей для указанной ветки?

Дальше можно будет трудоёмкость посчитать. :)

   Т.е. "O(n) от O(n^2) или больше" взято из пальца, как я и написал выше, так 
? :)

На досуге подумаю над этим вопросом, но быстро не обещаю. Это тебе Таблоида
напрячь надо, он любит такие задачки решать :)


Так же нет возможности организовать копирование веток, их слияние - т.
е. модификацию дерева.

   Опять без доказательства.

Тут у меня даже идеи нет с какой стороны подходить без явной рекурсии
или внешнего стека.
Может кто-нибудь предложит набросок идеи?

   Выбираешь копируемую ветку, но меняешь в ней старые ID на новые и
вставляешь результат в дерево.


П. С. Ну а если бы механизм СТЕ развился, чтобы покрывать хотя бы часть
этих задач, было бы просто нереально круто! :)
   А может ты просто не нашёл решения для части этих задач ?
Вот и спрашиваю, может ещё какие-то подходы есть которые я не увидел?

   Наверняка. И не обязательно связанные с рекурсией и с CTE. Например, можно
вынести связи в отдельную таблицу и писать туда не только пары непосредственных
parent\child, но и вообще всех child'ов данного parent'а. Другой подход описания
дерева с помощью границ множеств есть у Celko (и у DK на сайте). Также можно 
хранить
путь к корню дерева в строке в виде ID всех родителей разделённых спец. 
сепаратором.
Полно вариантов, не нужно останавливаться на классическом id, parent_id...

У меня не получается выразить с помощью СТЕ задачи требующие прохода
снизу вверх по дереву.

   Условие связки меняешь на обратное и начинаешь обход с нижнего уровня.


П. С.
Пробуя написать подсчёт детей породил такого вот монстрика.

with recursive
TREE (LEV, ID, PARENT_ID) as (
 select
   1 as LEV, s0.ID, s0.PARENT_ID
 from SYMPTOMS s0 where s0.PARENT_ID is null
 union all
 select
   t.LEV + 1, s1.ID, s1.PARENT_ID
 from SYMPTOMS s1 inner join TREE t on s1.PARENT_ID = t.ID
),
TREE_C (IDD, LEV, GRANDAD_ID, PARENT_ID) as (
 select
   s.ID, t.LEV, t.ID as GRANDAD_ID, t.PARENT_ID
 from SYMPTOMS s inner join TREE t on s.PARENT_ID = t.ID
 union all
 select
   sc.ID, tc.LEV, tc.GRANDAD_ID as GRANDAD_ID, tc.PARENT_ID
 from SYMPTOMS sc inner join TREE_C tc on sc.PARENT_ID = tc.IDD
)
select
 t.LEV, t.GRANDAD_ID, t.PARENT_ID, count(*)
from TREE_C t
group by 1, 2, 3

Пишет ошибку:
Column unknown
TC.IDD
At line 18, column 62
Хотя вроде имя столбца определено...
В чём проблема?

   С ходу не скажу, запрос вроде правильный... Если ты в нём уверен - пиши 
трекеру,
только добавь метаданные и немного данных.

П. П. С. Пока собирался ответить тут какой-то скандальчик замутился...

   У меня к тебе никаких претензий нет, даже наоборот - ты оживил эту 
конференцию,
за что и спасибо :) Провокатором неоднократно выступает Yurij и я каждый раз 
сожалею
о том, что что-то ему отвечаю. Ибо потом, после чтения его блога в ЖЖ, хочется 
пойти
отмыться...

--
Хорсун Влад

PS Я до сих пор не могу понять твоё упорное нежелание писать процедуры и твоё же
игнорирование этого моего вопроса.

Ответить