Привет всем.
Начал юзать эту конструкцию. Перед началом были вопросы они решились.
Но закралось смутное сомнение что будет ошибка. Поговорил с DY. Он сказал
нафиг серверу хранить то что он выбрал, он не хранит то что отдал по
сиквелу. Ну думаю логично, но все же хотелось бы в некоторых случаях чтобы
дубликаты не выпадали. Ситуация такая если развернуть дерево в обратную
сторону и сложжить его с другим деревом, то получаем рекурсию с
бесконечностью.
Для сиквела не в процедуре или триггере всебы ни чего. Но сегодня меня чуть
не порвали сервер в упор сжирал память и вылетал с "Unable to allocate
memory from operating system.". Я сразу сообразил что виновата рекурсия.
Получается при работе в триггере WITH всеже хранит данные а не тупо их
выкидывает. Значит можно привязать к WITH еще и типа [DISTINCT col, ...]
Проблема вылезла из особого принципа работы производста. Не возможно
подсчитать себестоимость если товар для производства в самом акте
производства. Для этого ставится табу на такой ввод данных. В результате
получаем.
WITH RECURSIVE T001_TREE as (
select distinct T003_1, T003_3, (select T003_1 from t001 where
T001.T001_1 = T1.T001_1b) as T003_1b
FROM T001 T1 where T1.T003_1 = 'aFcGzkMlus4YOBbB7w9WP2'
union all
--Предыдущие документы
select D.T003_1, D.T003_3, (select T003_1 from t001 where
T001.T001_1 = D.T001_1b) as T003_1b
FROM T001 D, T001_TREE Db
where D.T003_3 >= '15.12.2008' and D.T003_1 = Db.T003_1b
union all
--Поддокументы "например акты производства"
select D.T003_1, D.T003_3, (select T003_1 from t001 where
T001.T001_1 = D.T001_1b) as T003_1b
FROM T003 T3 join T001_TREE Db on T3.T003_1b = Db.T003_1 and
T3.IDDoc <> 53
join T001 D on D.T003_1 = T3.T003_1
)
select * from T001_TREE
но тут есть один нюанс под документы ломают всю нормальную логику дерева
т.к. у них свои даты и они имеют права списывать товар в разные периоды.
По сути в этом запросе мы ищем были ли ссылки на документ котором мы хотим
сослаться на торар из документа начиная с '15.12.2008' из документов
отписанных ранее.
Я сейчас решил эту задачу так
HList = b_StrListCreate(0, 1);
if (exists(
WITH RECURSIVE T001_TREE as (
select distinct T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = T1.T001_1b)) as T003_1b
FROM T001 T1 where T1.T003_1 = :VT003_1--T001.T001_1
=NEW.T001_1b
union all
--Предыдущие документы
select D.T003_1, b_StrListAddGet(:HList, (select T003_1 from t001
where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T001 D join T001_TREE Db on D.T003_1 = Db.T003_1b
where D.T003_3 >= :VT003_3
union all
--Поддокументы "например акты производства"
select D.T003_1, b_StrListAddGet(:HList, (select T003_1 from t001
where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T003 T3 join T001_TREE Db on T3.T003_1b = Db.T003_1 and
T3.IDDoc <> 53
join T001 D on D.T003_1 = T3.T003_1
) select * from T001_TREE where T003_1 = new.T003_1
))then begin
b_StrListDestroy(HList);
EXECUTE PROCEDURE ERROR('', 'Рекурсия недопустима.');
end
b_StrListDestroy(HList);
вывод напрашивается сам можно было реализовать это простым добавлением
возможности в WITH и написанное было бы такого вида в начале например
(может и както по другому)
WITH RECURSIVE T001_TREE as DISTINCT T003_1b (
И еще есть момент почему запрещено писать так
WITH RECURSIVE T001_TREE as (
select distinct T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = T1.T001_1b)) as T003_1b
FROM T001 T1 where T1.T003_1 = :VT003_1--T001.T001_1
=NEW.T001_1b
union all
--Предыдущие документы
select distinct D.T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T001 D join T001_TREE Db on D.T003_1 = Db.T003_1b
where D.T003_3 >= :VT003_3
union all
--Поддокументы "например акты производства"
select distinct D.T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T003 T3 join T001_TREE Db on T3.T003_1b = Db.T003_1 and
T3.IDDoc <> 53
join T001 D on D.T003_1 = T3.T003_1
) select * from T001_TREE where T003_1 = new.T003_1
то есть distinct в каждом сиквеле
суть заключается в следующем
1 сиквел делает выборку 1 строка из за distinct вместо 276!!!!!!!!!!!
2 сиквел возвращает кучу одинаковых значений получаем кучу лишних чтений
3 тоже что и в 2
Почему я чситаю что distinct должен работать в других частях смотрим
вот это --Предыдущие документы
select distinct D.T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T001 D join T001_TREE Db on D.T003_1 = Db.T003_1b
where D.T003_3 >= :VT003_3
это по сути есть при выполнении запроса
T001_TREE(X)
begin
--Предыдущие документы
select distinct D.T003_1, b_StrListAddGet(:HList, (select T003_1
from t001 where T001.T001_1 = D.T001_1b)) as T003_1b
FROM T001 D
where D.T003_3 >= :VT003_3 and D.T003_1 = :X
end
штуку написали классную но добавив в нее еще 2 функционала и мама дорогая
как круто все будет.