[ОТВЕТИТЬ]
12.07.2013 16:23
Explosion
 
В общем натворил вот такую штуку, но она чет не работает
Код:
create or replace function get_goods_ondate(art in string,
                                            mh  in number,
                                            dat in date) return number is
  Res number(14,3);
   begin  
   Select ost_dat
    into Res
    from (Select prod.article,g.quantity - (prih.wiq-prod.prq) as ost_dat from (Select ssc.article, sum(ssc.quantity) as prq, dsc.locationfrom
          from smspec ssc, smdocuments dsc
         where dsc.id = ssc.docid
           and dsc.doctype = ssc.doctype
           and ssc.doctype in ('CS','WO')
           and dsc.createdat >=
               to_date(dat, 'dd.mm.yyyy')
           and dsc.createdat <=
               to_date(to_char(sysdate,'dd.mm.yyyy'), 'dd.mm.yyyy') 
         group by ssc.article,dsc.locationfrom) prod,
         (Select swi.article,sum(swi.quantity) as wiq,dwi.locationto
          from smspec swi, smdocuments dwi
         where dwi.id = swi.docid
           and dwi.doctype = swi.doctype
           and swi.doctype = 'WI'
           and dwi.docstate = 3
           and dwi.createdat >=
               to_date(dat, 'dd.mm.yyyy')
           and dwi.createdat <=
               to_date(to_char(sysdate,'dd.mm.yyyy'), 'dd.mm.yyyy')
         group by swi.article,dwi.locationto) prih,
         smgoods g
         where prih.locationto = prod.locationfrom
         and g.storeloc = prod.locationfrom
         and g.article = art
         and g.storeloc = mh
         and g.article = prod.article
         and prod.article = prih.article);
  return(Res);
end get_goods_ondate;
Есть мысли почему?
Давно просто функции не писал)
12.07.2013 16:35
Troll
 
А что говорит-то? Если разбирать, то ошибку...
12.07.2013 17:43
svtl
 
Дело не в функции. Условие запроса попробуйте переписать по-другому.
where g.article = art
and g.storeloc = mh
and g.storeloc = prod.locationfrom(+)
and g.storeloc = prih.locationto(+)
and g.article = prod.article(+)
and g.article = prih.article(+)
У Вас получается, что будет результат тогда и только тогда, когда есть и расходы и приходы по артикулу. а ведь их может не быть.
(и я у sysdate по-другому конвертацию написала: to_date(sysdate,'dd.mm.yyyy') . но это некритично, кмк)

вот такой вариант у меня работает:
create or replace function get_goods_ondate
(art in string,mh in number,dat in date) return number is
Res number(14,3);
begin
Select ost_dat
into Res
from (
Select prod.article,
g.quantity - (nvl(prih.wiq, 0)-nvl(prod.prq, 0)) as ost_dat
from (Select ssc.article, sum(ssc.quantity) as prq, dsc.locationfrom
from supermag.smspec ssc, supermag.smdocuments dsc
where dsc.id = ssc.docid
and dsc.doctype = ssc.doctype
and ssc.doctype in ('CS','WO')
and dsc.createdat >=
to_date(dat, 'dd.mm.yyyy')
and dsc.createdat <=
to_date(sysdate,'dd.mm.yyyy')
group by ssc.article,dsc.locationfrom) prod,
(Select swi.article,sum(swi.quantity) as wiq,dwi.locationto
from supermag.smspec swi, supermag.smdocuments dwi
where dwi.id = swi.docid
and dwi.doctype = swi.doctype
and swi.doctype = 'WI'
and dwi.docstate = 3
and dwi.createdat >=
to_date(dat, 'dd.mm.yyyy')
and dwi.createdat <=
to_date(sysdate,'dd.mm.yyyy')
group by swi.article,dwi.locationto) prih,
supermag.smgoods g
where
g.article = art
and g.storeloc = mh
and g.storeloc = prod.locationfrom(+)
and g.storeloc = prih.locationto(+)
and g.article = prod.article(+)
and g.article = prih.article(+)
)
;
return(Res);
end get_goods_ondate;
12.07.2013 19:10
Dim
 
а чем встроенная функция не устраивает?
13.07.2013 14:50
Explosion
 
Да черт его знает))
Я видел что она есть...просто этим придется пользоваться постоянно и потом остатки на дату встроенная считает на конец дня. Или я ошибаюсь?
14.07.2013 00:19
svtl
 
Функция топикстартера не учитывает возвраты от покупателя по кассе, всякие внутренние перемещения, расходы на производство т.п., если они есть.
(но может их просто нет и не планируется :))
Я пользуюсь штатной процедурой.
Есть только одно "но", кмк, которе иногда бывает неудобно. Штатная записывает информацию во временную таблицу. Потом надо вытаскивать данные из нее. Поэтому доп. функция вполне имеет право на жизнь, если идет работа с небольшим кол-вом артикулов.
Вот всем остальном - штатная процедура считает быстрее простой селективной выборки. Ну и учитывает все возможные варианты движения товара.
24.07.2013 12:19
Explosion
 
А встроенную процедурку как из функции вызвать, подскажите плиз?
То что сейчас есть работает медленновато. А это как бэ не есть гуд
24.07.2013 13:47
svtl
 
Оно быстро и не будет.
По-поводу расчета Remains.Calc - сколько я помню, эта процедура считает оптимальным образом, с учетом параметров расчета остатков (статистики)

Как вызвать -
просто внутри вашей функции пишете вызов процедуры с параметрами.
у меня кусок кода может выглядеть так, например:

supermag.SQL_Filter.Clear_AllFilters;
supermag.SQL_Filter.Set_ArticleFromSQL('select article from supermag.ttidgroup');
supermag.SQL_Filter.Set_LocFromSQL('select id from TTLocList');

supermag.Remains.Calc(to_date(P_DATE, 'dd.mm.yyyy')-1, FALSE, 23, 0, FALSE); -- расчет остатков, в том числе ненулевые

ну и далее по своему коду - выборка из ttremains
24.07.2013 13:57
Explosion
 
я так попробовал, но оно чего-то ругается что Calc должен быть объявлен
24.07.2013 15:14
OlegON
 
Цитата:
Explosion я так попробовал, но оно чего-то ругается что Calc должен быть объявлен
Ошибки принято цитировать с кодом вызова, а не "чего-то"... И версию СМ лучше указывать.
24.07.2013 18:48
svtl
 
что-то не то. если напрямую запускаете,
то exec supermag.Remains.Calc....
25.07.2013 11:55
Explosion
 
Вызвал в функции стандартную процедуру
Пишет ORA-14551 Ошибка выполнения dml внутри запроса
25.07.2013 11:58
OlegON
 
Так покажи, как вызвал, второй раз прошу...
25.07.2013 12:39
svtl
 
ошибка из-за модификации данных внутри функции
проще - Calc запускать до селекта с соответствующими параметрами,
а в нужной функции использовать таблицу ttremains с остатками
25.07.2013 12:47
Explosion
 
В общем весь текст

create or replace function get_goods_ondate2(art in string,
mh in number,
dat in date) return number is
Res number(14, 3);
begin
Supermag.Remains.Calc(to_date(dat, 'dd.mm.yyyy'), false, 23, 1, false);
Select ost_dat
into Res
from (Select ttr.quantity as ost_dat,
ttr.article,
ttr.remdate,
ttr.storeloc
from supermag.ttremains ttr
where ttr.remdate = to_date(dat, 'dd.mm.yyyy')
and ttr.article = art
and ttr.storeloc = mh);
return(Res);
end get_goods_ondate2;
25.07.2013 12:55
Starter
 
А где функция планируется использоваться ? Не в Бизнес-анализе, случаем ?
25.07.2013 13:01
Explosion
 
нет. для отчета.
25.07.2013 13:03
OlegON
 
Цитата:
OlegON Так покажи, как вызвал, второй раз прошу...
третий раз прошу...
25.07.2013 13:12
Explosion
 
просто в запросе пишу
Select get_goods_ondate2(c.article,loc.id,'&Параметр_даты')
итд
25.07.2013 16:14
svtl
 
1. В инете предлагается решение с помощью автономных транзакций

Вот варинат, который у меня корректно отрабатывает:
create or replace function get_goods_ondate2(art in string,
mh in number,
dat in date) return number is
Res number(14, 3);
pragma autonomous_transaction;
begin
Supermag.Remains.Calc(to_date(dat, 'dd.mm.yyyy'), false, 23, 1, false);
commit;
.....
<далее по тексту функции>
end get_goods_ondate2;

select get_goods_ondate2('100172',2,to_date('25.07.2013', 'dd.mm.yyyy'))
from dual;

Но такая функция будет работать крайне медленно.
Вы не установили фильтры для этой процедуры (Обычно в отчетах CM используют для этого Supermag.SQL_Filter).
В результате в вашем варианте в ttremains попадают каждый раз
ВСЕ карточки с ненулевыми остатками по ВСЕМ местам хранения (можете после первого обращения к функции посмотреть содержимое ttremains).

Это процедура сделано для того, чтобы за один прием заполнить таблицу для всего набора условий - выбранных артикулов, мест хранения и пр.
25.07.2013 16:22
Starter
 
Вот вариант, автора не знаю. Но внутри Select также работать не будет. По поводу автономных транзакций - можно попробовать модифицировать ее.

create or replace
function supermag.GetOstToDate(AStoreLoc in supermag.smstorelocations.id%type, AArticle in supermag.smcard.article%type, OnDate in Date) return number
is
res number := 0;
begin
supermag.sql_filter.clear_allfilters;
supermag.sql_filter.add_location(AStoreLoc);
supermag.sql_filter.add_article(AArticle);
supermag.remains.calc(OnDate, False, 23, 0, True);
begin
select quantity
into res
from supermag.ttremains r
where r.article = AArticle;
return res;
exception when no_data_found then
return 0;
end;
end;
/
25.07.2013 16:28
whitewizard
 
Как оно всё замудрёно.
Проще ночью собирать таблицу с остатками на конец дня за нужный период.
Быстрее днём будут отчёты крутиться.
25.07.2013 16:40
svtl
 
можно и не ночью, а внутри отчета. но сначала посчитать 1 раз остатки а потом делать выборки из ttremains. Период у каждого исполнителя отчета свой может быть
25.07.2013 16:43
whitewizard
 
да все равно таблица копеешная будет
25.07.2013 21:39
svtl
 
угу.... если у меня сеть 50 магазинов + 300 000 карточек + дата любая - что я получу в результате?
кмк, эта процедура тем и хороша, что опирается на уже рассчитанные остатки на конец периода (в расчете статистики) и оптимальным по быстродействию образом расчитывает уже то, что мне надо.
т.е. велосипед уже изобретен :)
26.07.2013 03:36
whitewizard
 
Тогда быстрее будет уже рассчитанная таблица, в которую будут добавляться данные каждый день.
Разумеется, кроме случая, когда нужны остатки на единичные товары.
26.07.2013 15:46
Explosion
 
Задумался...
А кто-нибудь знает как можно эти остатки получить обходным путем?))
Ну к примеру через FastReport и оракл в связке
26.07.2013 15:47
Explosion
 
Или какой-нить прикладной программой дергать данные из отчета?
26.07.2013 15:49
Mtirt
 
Для каких целей это требуется? И какие именно остатки?
Может тебе текущих достаточно. Из smgoods выбрать и вся недолга...


Опции темы


Часовой пояс GMT +3, время: 02:38.

 

Форум сделан на основе vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot и OlegON
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.