Страница 3 из 3

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 09:52
hope
"Я прочел Ваше самое первое сообщение, первые две строки - 80 тыс МЦ, остатки 8 тыс. Вы сами его перечитайте - что Вы имели ввиду под этими цифрами в первом сообщении? Теперь Вы говорите, что 80 тыс остатков, раз остатки по всем есть?"

Ежедневно остатков примерно 8 тыс наименований, но если, как вы предлагаете, в отдельной таблице держать только МЦ, по которым есть остатки - эти остатки ведь будут не на одну конкретную дату, а, например, там будут все МЦ, по которым были остатки в течение года, вот и получится, что эта таблица будет содержать почти весь каталог МЦ. И далее вы предлагаете все новые МЦ добавлять в эту таблицу - вот и получится весь каталог МЦ в этой таблице. Или что-то не так поняла?

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 10:01
hope
spark писал(а):
hope писал(а):Может кто-нибудь в курсе: как сделать, чтобы в Access поля типа Comp отображались правильно?

Код: Выделить всё

SELECT dbo.ToInt64(F$NREC) as NREC FROM dbo.T$BASEDOC
Т.е. в Access мне не нужно настраивать связь с таблицами, в нужно запросом вытягивать данные?

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 10:12
hope
Den писал(а):ecasoft, топикстартер просто привел немного лишней информации... )Остатки за период ..это как ? Остатки - они всегда на какую то дату, насколько я себе представлял...
Все сводится к тому(упрощенно пишу конечно...) чтобы выловить из saldomc на n-ую дату разрез (разрез тот, который нужен в соответствии с методом учета по складу на предпритяии..имею ввиду подраз -мол-мц, подраз-мол-мц-партия и т.д....) по которому кол-во остатка не нулевое. И, конечно, тут katmc имеет к данной задаче вообщем то весьма косвенное отношение
Вся проблема в том, что в таблице SaldoMc сальдо по МЦ хранится по разным датам, из этих записей надо отобрать запись с самой поздней датой, да еще учесть разрезы - т.е. по каждому разрезу надо найти запись с самой поздней датой.
Чтобы это сделать нужно либо делать циклы по разрезам. Либо для каждой записи сальдо проверять - нашли ли уже по этому разрезу сальдо - что на мой взгляд не эффективно.

Может я неправильно мыслю? Есть еще какой-то вариант найти сальдо?

В таблице SaldoMc вроде бы есть еще записи с сальдо по предприятию - может их сначала отобрать? И по ним уже искать сальдо в нужном разрезе?

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 12:11
spark
hope писал(а):
spark писал(а):
hope писал(а):Может кто-нибудь в курсе: как сделать, чтобы в Access поля типа Comp отображались правильно?

Код: Выделить всё

SELECT dbo.ToInt64(F$NREC) as NREC FROM dbo.T$BASEDOC
Т.е. в Access мне не нужно настраивать связь с таблицами, в нужно запросом вытягивать данные?
В Access есть ограничение на количество индексов и он отказывается многие таблицы галактики принимать как связанные таблицы. Поэтому я делаю запросом к серверу MS SQL.

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 12:29
Den
hope писал(а): Вся проблема в том, что в таблице SaldoMc сальдо по МЦ хранится по разным датам, из этих записей надо отобрать запись с самой поздней датой, да еще учесть разрезы - т.е. по каждому разрезу надо найти запись с самой поздней датой...
Ну примерно вот так делал недавно (@MyDate - на какую дату получаем остатки,@CurPodr- по какому подразделению):

Код: Выделить всё

select mc.f$name,
				 isnull(mol.f$name,'не опеределен') as mol,
				 isnull(party.f$name,'не определен') as party,
				  t1.f$kolp-t1.f$kolr as kolka,
				  t1.f$srprice as price
	
				
		  from (
				  select s.f$nrec, s.f$cmc, s.f$cmol, s.f$cparty, s.f$cpodr, 
					s.f$kolp, s.f$kolr, s.f$kol, s.f$srprice, 
					s.f$dsaldo, max(s.f$dsaldo) OVER(partition by s.f$cmc, s.f$cmol, s.f$cparty, s.f$cpodr) as maxdate			
			       from t$saldomc s inner join t$katpodr podr on s.f$cpodr=podr.f$nrec 
					where s.f$dsaldo<=@MyDate and s.f$sp=0 and s.f$cpodr=@CurPodr --and s.f$cmol=@CurMol				
				) t1
			inner join t$katmc mc on t1.f$cmc=mc.f$nrec
			left join t$katmol mol on t1.f$cmol=mol.f$nrec
			left join t$katparty party on t1.f$cparty=party.f$nrec           
			where f$dsaldo = maxdate and (t1.f$kolp-t1.f$kolr)<>0 
             order by mc.f$name
Ест-но код под свои условия делал, но допилить как нужно его недолго. При 11 млн записей по saldomc отрабатывает за пару секунд.

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 16:53
ecasoft
hope писал(а):"Я прочел Ваше самое первое сообщение, первые две строки - 80 тыс МЦ, остатки 8 тыс. Вы сами его перечитайте - что Вы имели ввиду под этими цифрами в первом сообщении? Теперь Вы говорите, что 80 тыс остатков, раз остатки по всем есть?"

Ежедневно остатков примерно 8 тыс наименований, но если, как вы предлагаете, в отдельной таблице держать только МЦ, по которым есть остатки - эти остатки ведь будут не на одну конкретную дату, а, например, там будут все МЦ, по которым были остатки в течение года, вот и получится, что эта таблица будет содержать почти весь каталог МЦ. И далее вы предлагаете все новые МЦ добавлять в эту таблицу - вот и получится весь каталог МЦ в этой таблице. Или что-то не так поняла?
Идея состоит в том, чтобы значительно уменьшить пространство рассчета. Она работает в том случае, если у Вас МЦ периолически заменяются другими (из-за этого и получается, что остатки по старым МЦ, не появляются после некоторого периода и остатков 8 тыс, а МЦ 80 тыс.) Если из 80 тыс 50 тыс не появлялись в движении последний год, то их можно выбросить из анализа и тем самым сократить расчет. Когда я прочел наш первый пост, то так и понял, что есть старые МЦ, которые давно перестали участвовать в движении по складу. Это обычное дело для торговых компаний. Убрать эту старую информацию можно отобрав только свежие МЦ в отдельную таблицу ОДИН раз. И отталкиваться в SQL не от всего каталога МЦ, а от этой таблицы.

Я не понимаю, почему Вы упорно говорите, что получится опять весь каталог? С чего он получится? Что у Вас все 8 тыс остатков в день продают, а на след. день покупают все 8 тыс других МЦ и так каждый день? Только в этом слкчае получится весь каталог.

Re: Быстро посчитать сальдо по МЦ

Добавлено: 05 май 2012, 17:25
ecasoft
Давайте поясню на программистком языке Галактики.

Смотрим индексы для SAldoMC и вижим, что у них стоит вначале cMC, а далее уже cPord cMol ...a DSALDO ВООБЩЕ в самом конце.

Это значит, чтобы получить остатки по конкретному складу вам надо смотреть ВСЕ МЦ, за все дату вне зависимости от того есть они там или нет (или были или нет когда-то). А если отберете, то будете отбирать только те, что имеют остатки.

Можно еще пойти дальше и увязать МЦ и где они хранятся по подразделениям в отдельной таблице. Тогда по конкретному подразделению Вы будете искать только среди МЦ которые на нем есть и только у которых были остатки, а не сплошем перебором как это делается сейчас АБСОЛЮТНО при всех запросах (т.к. нет нужных индексов просто).
Когда тут пишут примеры на MS SQL, то сервер будет строить в памяти нужные индексы (все же это настоящий SQL), но все равно никогда ему не построить быстрее, если заранее будет проведен описанный выше предварительный анализ информации по сальдо.

Re: Быстро посчитать сальдо по МЦ

Добавлено: 10 май 2012, 10:04
hope
ecasoft! Я все прекрасно понимаю! Просто 50 тысяч МЦ, имхо, не спасут ситуацию - все-равно долго отбираются остатки.
Но все-равно ваш вариант тоже попробую - спасибо за идею!

Re: Быстро посчитать сальдо по МЦ

Добавлено: 18 май 2012, 14:43
hope
ecasoft! не подскажите - какую таблицу таблицу вы используете для хранения ссылок на мц?

Re: Быстро посчитать сальдо по МЦ

Добавлено: 04 июл 2012, 14:58
lStep
Это штатный способ пересчета. Он чёткий, но не быстрый:
oiko писал(а):Store_Init;
Store_ReInit;
Store_TypeOstatki(TRUE) ; // входящие остатки
Store_SkladProizv(0);
Store_Run(date1,comp(-2),comp(-2),comp(0),comp(0), true, false, false);
Вот способ побыстрее на SaldoFND + SaldoMC:

Код: Выделить всё

var

 SaldoDate  : Date;     //  - на какую дату
 SaldoBase  : Word;     //  - Для какой базы
 Saldo_SP   : word;     //  - 0= склад 1= производство
 Saldo_Vhod : boolean;  //  - True = входящий остаток ; False = исходящий; 


Table Struct MTSaldo
(
   cmc       : Comp,    // Наименование
   cPodr     : Comp,    // Наименование
   cMol      : Comp,    // Наименование
   cparty    : Comp,    // Наименование
   KOL     : double,
   SRPRICE : double,
   SRP     : double
)
with index 
( 
  MTSaldo1 = cPodr+cMol,  
  MTSaldo2 = cMol 
);

       
       and            ROOT == SaldoFND.SP 
       and       Saldo_SP  == SaldoFND.SP
       and     SaldoFND.SP == SaldoMC.SP
       and      SaldoDate >>= SaldoMC.dSaldo   
       and SaldoFND.cmc    == SaldoMC.cmc   
       and SaldoFND.cpodr  == SaldoMC.cpodr 
       and SaldoFND.cmol   == SaldoMC.cmol  
       and SaldoFND.cparty == SaldoMC.cparty



Function CalcSaldoMC(   pSaldoDate  : Date;     //  - на какую дату
                      NewSaldoBase  : Word;     //  - Для какой базы
                      NewSaldo_SP   : word;    // - 0= склад 1= производство
                      NewSaldo_Vhod : boolean; // - True = входящий остаток ; False = исходящий; 
                      pUseTekSaldo  : boolean  // - True - если можно, ползовать TekSaldo (Цен не будет)
                    ): boolean; // True, Если остатки правиьно посчитались

{
  var  NewSaldoDate  : Date;     //  - на какую дату

  NewSaldoDate := if(NewSaldo_Vhod,pSaldoDate,Add_Day(pSaldoDate,1));


  if (SaldoDate = Date(0,0,0)) or
     (NewSaldoDate <> SaldoDate) or 
     (NewSaldoBase <> SaldoBase) or
     (NewSaldo_SP  <> Saldo_SP ) then
  { //расчёт
     SetNBase(NewSaldoBase);

     set SaldoBase  := NewSaldoBase ;
     set SaldoDate  := NewSaldoDate ;
     set Saldo_SP   := NewSaldo_SP  ;

     if (SaldoDate = Add_Day(cur_date,1)) and pUseTekSaldo and (tsOk= getfirst TekSaldo)then
     { 
     SetVisualHeader('База N'+string(CurNBase)+ chr(13)+
                         'Просмотр остатков на Сегодня'+chr(13)+
                         '=================');
       delete all MTSaldo;

       _Loop TekSaldo 
       if TekSaldo.Kol <> 0 then
       {
         insert MTSaldo set  MTSaldo.cmc    := TekSaldo.cmc   ,
                             MTSaldo.cpodr  := TekSaldo.cpodr ,
                             MTSaldo.cmol   := TekSaldo.cmol  ,
                             MTSaldo.cparty := TekSaldo.cparty,
                             MTSaldo.Kol    := TekSaldo.Kol   ;
       }
     } // if 
     else
     if (tsOk= getfirst SaldoFND) then
     {
     SetVisualHeader('База N'+string(CurNBase)+ chr(13)+
                         'Расчёт входящих остатков на:'+NewSaldoDate+chr(13)+
                         '=================');
         var i1: integer; 
         i1 := 0;
       delete all MTSaldo;

         i1 := 0;
       _loop SaldoFnd
       {               
         if (tsOk = getLast SaldoMC) and (SaldoMC.Kol <> 0) then
         {
            Insert current MTSaldo set 
                           MTSaldo.cmc    := SaldoMC.cmc   ,
                           MTSaldo.cpodr  := SaldoMC.cpodr ,
                           MTSaldo.cmol   := SaldoMC.cmol  ,
                           MTSaldo.cparty := SaldoMC.cparty,
                             MTSaldo.Kol    := SaldoMC.Kol     ,
                             MTSaldo.SRPRICE:= SALDOMC.SRPRICE ,
                             MTSaldo.SRP    := SALDOMC.SRP     ;
         }
       }
     } else SaldoDate := Date(0,0,0);
  }

  if (SaldoDate = Date(0,0,0)) then message ('Ошибка расчета остатков на '+NewSaldoDate);
  CalcSaldoMC := (SaldoDate <> Date(0,0,0));
}
Насчет "максимально быстро" вспомнил анекдот про 1000знаков в минуту :)
Любое отступление при пересчете от SaldFND+SaldoMC приведёт к "приблизительному результату".
Можно так:
1) Считаем сальдовые остатки и вносим интересующие нас МЦ в ТАБЛИЦУ_X
2) В течении какого-то периода пользуем быстрый расчет ТАБЛИЦа_X + SaldFND+SaldoMC
Но следует иметь в виду, что новые МЦ, что придут на склад в отчете (п.2) не появятся до обновления ТАБЛИЦа_X в.п.1
И тут надо заручиться ГАРАНТИЕЙ, что за такой остаток вам голову не уволят.

Re: Быстро посчитать сальдо по МЦ

Добавлено: 04 июл 2012, 15:11
edward_K
L_SKLREP_RES_810170.txt

Код: Выделить всё

* ПРОБЛЕМА В ПИР: 101.49010
* ПЕРВОЕ РЕШЕНИЕ: NEW
* КРАТКОЕ ОПИСАНИЕ: Долго формируется отчет наличия остатков по складам 
(партионный учет)
* ПРОЕКТ: Складской учет
* ДЕТАЛИЗАЦИЯ: Наличие\по складам
# ЧТО ИЗМЕНЕНО:  ПИР 102.110377 - Долго формируется отчет наличия остатков по 
складам (партионный учет)- 10.10.2011 была решена. G_SKL 8.10.08.0.
Перед праздниками были установлены все последние патчи - проблема возникла 
вновь.

//
Долго формируется отчет "Ведомость наличия -  по складам" для складов ОРСа. 
Продукты учитываются по партиям. По всем другим складам - партий нет.
Для сравнения: Склад №1 БПТОиК - остатков на 78 079 544руб. (3 мин.)
               Столовая №1 - остатков на 750 314руб. (40 мин.)
Если сформировать отчет "Ведомость наличия - по партиям" для Столовой №1 - 
(2мин.).
Необходимо, чтобы отчет "Ведомость наличия - по складам" для складов ОРСа (учет 
по партиям) формировался 2-3мин.
Отчет о старой системе прилагается.
//

# КАК ИЗМЕНЕНО: Проблема с быстродействием решена, ускорение от нескольких раз, 
до нескольких десятков раз. Код формирования остатков был переведен на DSQL, и 
внедрен в интерфейсы "наличия по складам" и "наличие по складам в разрезе мол"
* * *

В своем отчете никто не запрещает взывать свою выборку получения остатков. Возни тока больше чем с вызовом стандартной. Опять же можно и хранимку выполнить.