Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Vlad Khorsun


"Boltik Evgeny" ...


Еще обнаружил утечку в моем случае сервер в диспетчере задач как только 
открываю код с WITH. Сжерает несколько мегов.
Проявляется на чистой базе из Эксперта. Могу выложить архив. Но размер его 85 
мегов :(.
Самому сегодня домой его пришлось тянуть с другого города.
Если надо то выложу скажи почтовый я отправлю откуда забрать или пиша в асю 
344208852


   А то ты мой адрес не знаешь :)

hvlad at users sourceforge net 





Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Boltik Evgeny



"Vlad Khorsun"  
сообщил/сообщила в новостях следующее: news:gmcvih$av...@ger.gmane.org...


"Boltik Evgeny" ...

Вот сижу в догадках как и в первые разы. Баг иль не баг. По идее при 
DISTINCT должно быть меньше.


   Без примера данных я ничего не могу сказать


Еще обнаружил утечку в моем случае сервер в диспетчере задач как только 
открываю код с WITH. Сжерает несколько мегов.
Проявляется на чистой базе из Эксперта. Могу выложить архив. Но размер его 
85 мегов :(.

Самому сегодня домой его пришлось тянуть с другого города.
Если надо то выложу скажи почтовый я отправлю откуда забрать или пиша в асю 
344208852 





Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Vlad Khorsun


"Boltik Evgeny" ...


Вот сижу в догадках как и в первые разы. Баг иль не баг. По идее при DISTINCT 
должно быть меньше.


   Без примера данных я ничего не могу сказать

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





Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Boltik Evgeny



 (SELECT DISTINCT S2.T003_1,
   (select F.T003_1 from t001 F where F.T001_1 = S2.T001_1b) 
as T003_1b,

   T3.T003_1b as T3_T003_1b
 FROM T003 T3 join T001 S2 on S2.T003_1 = T3.T003_1
 where T3.IDDoc <> 53) D2 on  D2.T3_T003_1b = Db.T003_1
)
весь результат 1991 строка но если внизу
 (SELECT /*DISTINCT */S2.T003_1
то почемуто всего 341 строка

Вот сижу в догадках как и в первые разы. Баг иль не баг. По идее при 
DISTINCT должно быть меньше.



А теперь еще прикол
 (SELECT DISTINCT S2.T003_1,
   (select F.T003_1 from t001 F where F.T001_1 = S2.T001_1b) as 
T003_1b,

   T3.T003_1b as T3_T003_1b
 FROM T003 T3 join T001 S2 on S2.T003_1 = T3.T003_1
 where T3.IDDoc <> 53) D2 on  D2.T3_T003_1b = Db.T003_1
)
select distinct T003_1
from T001_TREE
получаем 274 записи

 (SELECT /*DISTINCT */S2.T003_1,
   (select F.T003_1 from t001 F where F.T001_1 = S2.T001_1b) as 
T003_1b,

   T3.T003_1b as T3_T003_1b
 FROM T003 T3 join T001 S2 on S2.T003_1 = T3.T003_1
 where T3.IDDoc <> 53) D2 on  D2.T3_T003_1b = Db.T003_1
)
select distinct T003_1
from T001_TREE
получаем 74 записи
Это как так? 





Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Boltik Evgeny



   Нихрена не понял, как обычно


СП, что помогаешь горю.


вывод напрашивается сам можно было реализовать это простым добавлением
возможности в WITH  и написанное было бы такого вида в начале например
(может и както по другому)
WITH RECURSIVE T001_TREE as DISTINCT T003_1b (


   Что мешает делать выборку из T003_1b с 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

Стало

 select D.T003_1, b_StrListAddGet(:HList, (select T003_1 from t001 
where T001.T001_1 = D.T001_1b)) as T003_1b
   FROM (SELECT DISTINCT T003_1 FROM T001 where T003_3 >= 
:VT003_3) D

   join T001_TREE Db on D.T003_1 = Db.T003_1b



За мысль огромное СП. Но я когда начинал так пробовал. Решил еще раз и снова 
возникли вопросы сделал так

WITH RECURSIVE T001_TREE as (
 select distinct T003_1, (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 D1.T003_1, D1.T003_1b
   FROM T001_TREE Db join (SELECT DISTINCT S1.T003_1,
 (select F.T003_1 from t001 F where F.T001_1 = S1.T001_1b) as 
T003_1b

 FROM T001 S1 where T003_3 >= '15.12.2008') D1
   on D1.T003_1 = Db.T003_1b
 union all
 --Поддокументы "например акты производства"
 select  D2.T003_1, D2.T003_1b
   FROM T001_TREE Db join
 (SELECT DISTINCT S2.T003_1,
   (select F.T003_1 from t001 F where F.T001_1 = S2.T001_1b) as 
T003_1b,

   T3.T003_1b as T3_T003_1b
 FROM T003 T3 join T001 S2 on S2.T003_1 = T3.T003_1
 where T3.IDDoc <> 53) D2 on  D2.T3_T003_1b = Db.T003_1
)
весь результат 1991 строка но если внизу
 (SELECT /*DISTINCT */S2.T003_1
то почемуто всего 341 строка

Вот сижу в догадках как и в первые разы. Баг иль не баг. По идее при 
DISTINCT должно быть меньше. 





Re: WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Vlad Khorsun


   Нихрена не понял, как обычно


вывод напрашивается сам можно было реализовать это простым добавлением
возможности в WITH  и написанное было бы такого вида в начале например
(может и както по другому)
WITH RECURSIVE T001_TREE as DISTINCT T003_1b (


   Что мешает делать выборку из T003_1b с 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

Стало

 select D.T003_1, b_StrListAddGet(:HList, (select T003_1 from t001 
where T001.T001_1 = D.T001_1b)) as T003_1b
   FROM (SELECT DISTINCT T003_1 FROM T001 where T003_3 >= :VT003_3) D
   join T001_TREE Db on D.T003_1 = Db.T003_1b

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




WITH RECURSIVE нуансы которые хотелось чтоб учли и добавили

2009-02-04 Пенетрантность Boltik Evgeny
Привет всем.

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