Привет всем.

Начал юзать эту конструкцию. Перед началом были вопросы они решились.
Но закралось смутное сомнение что будет ошибка. Поговорил с 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 функционала и мама дорогая 
как круто все будет. 


Ответить