Имя: Пароль:
1C
1C 7.7
v7: Оптимизация запроса. Склад
0 Invzor
 
20.04.15
14:18
Здравствуйте. Есть небольшой отчет по складам. Остатки по складам. Обрабатывается пол дня... можно ли его как-то оптимизировать?


Перем ТабСВ;
//*******************************************
Процедура ПриОткрытии()
//    Склад = Константа.СкладПоУмолчанию;    //ЗАКОМЕНТИЛ!
КонецПроцедуры  

Процедура Сформировать()
    ДатаНачала = НачМесяца(ПериодОтчета);
    датаКонец = КонМесяца(ПериодОтчета);
    ТабСв = СоздатьОбъект("таблицаЗначений");  
    ТабСВ.НоваяКолонка("номер","число");
    ТабСв.НоваяКолонка("Материал","Справочник.Номенклатура");
    ТабСв.НоваяКолонка("ОстатокНаНачало","число");
    ТабСв.НоваяКолонка("ОстатокНаКонец","число");
    ТабСв.НоваяКолонка("Приход","число");
    ТабСв.НоваяКолонка("Расход","число");
    ТабСв.НоваяКолонка("Склад","Справочник.Склады");
    Запрос = СоздатьОбъект("Запрос");
    датаНач = Дата(1,1,2011);  //стоял 2005
    //    |Период с ДатаНач по ДатаНачала;    // стояло
    ТекстЗапроса = "
    |Период с ДатаНач по ДатаКонец;
    |Материал = Регистр.ОстаткиНаСкладе.Материал;
    |Склад = Регистр.ОстаткиНаСкладе.Склад;
    |Количество = Регистр.ОстаткиНаСкладе.Количество;
    |Функция КоличествоКонОст = КонОст(Количество);
    |Группировка Материал;
    |Группировка Склад;
    |Условие (Материал в ВыбрМатериалГруппа);
    |Условие (Склад в Склад);
    |";
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Пока Запрос.Группировка(1) = 1 Цикл
        ТабСв.НоваяСтрока();  
        ТабСВ.номер = Запрос.Материал.Код;
        ТабСв.Материал = Запрос.Материал;  
        ТабСв.ОстатокНаНачало = запрос.количествоКонОст;
        ТабСв.ОстатокНаКонец = 0;
        ТабСв.Приход = 0;
        ТабСв.Расход = 0;  
        ТабСв.Склад = Запрос.Склад;
    
    КонецЦикла;
    //----------------------------
    ТекстЗапроса = "
    |Период с ДатаНачала по ДатаКонец;
    |Материал = Регистр.ОстаткиНаСкладе.Материал;
    |Склад = Регистр.ОстаткиНаСкладе.Склад;
    |Количество = Регистр.ОстаткиНаСкладе.Количество;
    |Функция КоличествоКонОст = КонОст(Количество);
    |Группировка Материал;
    |Группировка Склад;
    |Условие (Материал в ВыбрМатериалГруппа);
    |Условие (Склад в Склад);
    |";
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
        Возврат;
    КонецЕсли;
    Пока Запрос.Группировка(1) = 1 Цикл
        нСтр = 0;
        Если ТабСв.НайтиЗначение(Запрос.Материал,нСтр,"Материал")=1 Тогда
            ТабСв.ПолучитьСтрокуПоНомеру(нСтр);
            ТабСв.ОстатокНаКонец = Запрос.КоличествоКонОст;  
    
        Иначе
            ТабСв.НоваяСтрока();      
            ТабСВ.номер = Запрос.Материал.Код;
            ТабСв.Материал = запрос.Материал;
            ТабСв.ОстатокНаНачало = 0;
            ТабСв.ОстатокНаКонец = Запрос.КоличествоКонОст;
            ТабСв.Приход = 0;
            ТабСв.Расход = 0;
    
        КонецЕсли;
        
    КонецЦикла;
    //-------------------------
    таб = СоздатьОбъект("Таблица");  
    таб.ВывестиСекцию("Заголовок");  
    табсв.ВыбратьСтроки();          
    ИтогоПриход = 0;
    ИтогоРасход = 0;
        итогСуммаРасхода=0;
    Пока табсв.ПолучитьСтроку() = 1 Цикл
        Материал = ТабСВ.Материал;
        Приход = 0;
        Расход = 0;  
        НомерКарточки = Материал.Код;
        РегОст = СоздатьОбъект("Регистр.ОстаткиНаСкладе");
        РегОст.УстановитьФильтр(Материал);
        РегОст.ВыбратьДвижения(ДатаНачала,ДатаКонец,);
        Пока  РегОст.ПолучитьДвижение()=1  Цикл  
            
    
            Если РегОст.Приход =1 тогда
            //    Если РегОст.Склад = ВыбСклад тогда //////////////////////////
        
            //        ТабСв.Склад =  ВыбСклад;       //////////////////////////
                    Приход=Приход+РегОст.Количество;// КонецЕсли;
                
            иначе
        //        Если РегОст.Склад = ВыбСклад тогда //////////////////////////
                  
            //        ТабСв.Склад = ВыбСклад;////////////////////////////
                    Расход=Расход+РегОст.Количество; // КонецЕсли;
                        
            конецЕсли;                  
        КонецЦикла;
        ТабСВ.Приход = Приход;
        ТабСВ.Расход = Расход;
        //------расчет средней цены-----    
        
    //------конец расчета средней цены---
    КонецЦикла;    
    ТабСВ.Сортировать("номер");  
    ТабСВ.ВыбратьСтроки();

    Пока ТабСВ.ПолучитьСтроку() = 1 Цикл
        
    //    Если ТабСв.Склад = выбСклад тогда
        срЦена = ПолучитьСреднююЦену(ТабСВ.Материал);
        приходНаНачало = ПолучитьСуммуПрихода(ТабСВ.Материал,ДатаНачала);
        приходНаКонец = ПолучитьСуммуПрихода(ТабСВ.Материал,датаКонец);
        расходНаНачало = ПолучитьСуммуРасхода(ТабСВ.Материал,ДатаНачала);
        расходНаКонец = ПолучитьСуммуРасхода(ТабСВ.Материал,датаКонец);  
        суммаНаНачало = приходНаНачало - расходНаНачало;
        СуммаНаКонец = приходНаКонец - расходНаКонец;
        суммаПрихода = приходНаКонец - приходНаНачало;  
        суммаРасхода = расходНаКонец - расходНаНачало;  
        ИтогоПриход=ИтогоПриход+суммаПрихода;
        ИтогоРасход=ИтогоРасход+суммаРасхода;
        итогСуммаРасхода=итогСуммаРасхода+СуммаНаКонец;
        таб.ВывестиСекцию("Тело"); //КонецЕсли;
    КонецЦикла;
       таб.ВывестиСекцию("Итого");    
       таб.ТолькоПросмотр(1);
    таб.Показать();
    //-------------------------
    
    
    
КонецПроцедуры
1 mikecool
 
20.04.15
14:20
избавиться от
        РегОст = СоздатьОбъект("Регистр.ОстаткиНаСкладе");
        РегОст.УстановитьФильтр(Материал);
        РегОст.ВыбратьДвижения(ДатаНачала,ДатаКонец,);
в цикле
добавить данные в основной запрос
2 Invzor
 
20.04.15
14:23
(1) там два запроса... с них инфа собирается в тамзначений... и потом уже из балицы анализируется вся инфа с этих двух запросов.... не получится вставить регистры туда...
3 Злопчинский
 
20.04.15
14:31
(2) все кроме последнего цикла решается одним запросом и его обходом
последний цикл - хз что у тебя там в получитьсуммы..()
включи отладчик с замером времени и смотри где оно жрется
4 mikecool
 
20.04.15
14:31
(2) тогда смирись
5 МихаилМ
 
20.04.15
15:37
для sql версии

замените группировку на группировна без упорядочивания без групп.

ускорение в работе запроса будет за счет
того, что при упорядочивании 1с для каждого поля группировки и каждой строки выборки 1с77 генерирует микро запрос к субд.

замените отбор по вхождению в группу на

конструкцию в запросе "  |Условие (Материал = материалы[0] ИЛИ .. Материал = материалы[N]  )"


соответственно массив материалы[] нужно получить путем расчета

ускорение будет , тк 1с77 для каждого элемента конструкции В создает  хранимую процедуру исполняет ее и удаляет

ограничение такого подхода ~2200 элементов в массиве.