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

ПНР и сопровождение

Модераторы: m0p3e, edward_K, Модераторы

hope
Местный житель
Сообщения: 1353
Зарегистрирован: 29 мар 2005, 17:49
Контактная информация:

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

Сообщение hope »

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

Ежедневно остатков примерно 8 тыс наименований, но если, как вы предлагаете, в отдельной таблице держать только МЦ, по которым есть остатки - эти остатки ведь будут не на одну конкретную дату, а, например, там будут все МЦ, по которым были остатки в течение года, вот и получится, что эта таблица будет содержать почти весь каталог МЦ. И далее вы предлагаете все новые МЦ добавлять в эту таблицу - вот и получится весь каталог МЦ в этой таблице. Или что-то не так поняла?
hope
Местный житель
Сообщения: 1353
Зарегистрирован: 29 мар 2005, 17:49
Контактная информация:

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

Сообщение hope »

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

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

SELECT dbo.ToInt64(F$NREC) as NREC FROM dbo.T$BASEDOC
Т.е. в Access мне не нужно настраивать связь с таблицами, в нужно запросом вытягивать данные?
hope
Местный житель
Сообщения: 1353
Зарегистрирован: 29 мар 2005, 17:49
Контактная информация:

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

Сообщение hope »

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

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

В таблице SaldoMc вроде бы есть еще записи с сальдо по предприятию - может их сначала отобрать? И по ним уже искать сальдо в нужном разрезе?
spark
Местный житель
Сообщения: 476
Зарегистрирован: 19 окт 2005, 13:38
Контактная информация:

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

Сообщение spark »

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

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

SELECT dbo.ToInt64(F$NREC) as NREC FROM dbo.T$BASEDOC
Т.е. в Access мне не нужно настраивать связь с таблицами, в нужно запросом вытягивать данные?
В Access есть ограничение на количество индексов и он отказывается многие таблицы галактики принимать как связанные таблицы. Поэтому я делаю запросом к серверу MS SQL.
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

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

Сообщение 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 отрабатывает за пару секунд.
ecasoft
Местный житель
Сообщения: 645
Зарегистрирован: 29 мар 2005, 17:49
Откуда: г.Королев МО ООО "Эффективная Комплексная Автоматизация- СОФТ"

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

Сообщение ecasoft »

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

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

Я не понимаю, почему Вы упорно говорите, что получится опять весь каталог? С чего он получится? Что у Вас все 8 тыс остатков в день продают, а на след. день покупают все 8 тыс других МЦ и так каждый день? Только в этом слкчае получится весь каталог.
ecasoft
Местный житель
Сообщения: 645
Зарегистрирован: 29 мар 2005, 17:49
Откуда: г.Королев МО ООО "Эффективная Комплексная Автоматизация- СОФТ"

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

Сообщение ecasoft »

Давайте поясню на программистком языке Галактики.

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

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

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

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

Сообщение hope »

ecasoft! Я все прекрасно понимаю! Просто 50 тысяч МЦ, имхо, не спасут ситуацию - все-равно долго отбираются остатки.
Но все-равно ваш вариант тоже попробую - спасибо за идею!
hope
Местный житель
Сообщения: 1353
Зарегистрирован: 29 мар 2005, 17:49
Контактная информация:

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

Сообщение hope »

ecasoft! не подскажите - какую таблицу таблицу вы используете для хранения ссылок на мц?
lStep
Новичок
Сообщения: 28
Зарегистрирован: 27 июл 2006, 16:49

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

Сообщение 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
И тут надо заручиться ГАРАНТИЕЙ, что за такой остаток вам голову не уволят.
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5187
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

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

Сообщение 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, и 
внедрен в интерфейсы "наличия по складам" и "наличие по складам в разрезе мол"
* * *

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