Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Оптимизация запроса остатков по складам для Перемещения
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Программирование в 1С Предприятие 8.2 > Программирование обычных форм 1С 8.2 и не интерфейсной логики
bizisoft
Здравствуйте.
Наши креативщики не унимаются и желают видеть в макете документа ПеремещениеТовароа дополнительные столбцы с остатками по складам, якобы, чтобы можно было видеть остаток.
Хотели видеть по всем складам, но уговорил только чтобы были остатки складов Отправитель и Получатель.

Сначала сделал через такой запрос (вернее два запроса для склада отправитель и склада получатель):
                Запрос = Новый Запрос;
        Запрос.Текст =
           "ВЫБРАТЬ
           |    ОстаткиТоваровКомпанииОстатки.Номенклатура,
           |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
           |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток
           |ИЗ
           |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки КАК ОстаткиТоваровКомпанииОстатки
           |ГДЕ
           |    ОстаткиТоваровКомпанииОстатки.Номенклатура = &Номенклатура
           |    И ОстаткиТоваровКомпанииОстатки.СкладКомпании = &СкладКомпании";            

        Запрос.УстановитьПараметр("Номенклатура", СтрокаТабличнойЧасти.Номенклатура);
        Запрос.УстановитьПараметр("СкладКомпании", ЭтотОбъект.СкладКомпании);
        
        Выборка = Запрос.Выполнить().Выбрать();
        ОстатокНаСкладе = 0;
        Пока Выборка.Следующий() Цикл    
            ОстатокНаСкладе = Выборка.КоличествоОстаток;
        КонецЦикла;
                ОбластьТовар.Параметры.Остаток = ОстатокНаСкладе;  
                ....  // Тут выполняется второй запрос для склада получателя
        ОбластьТовар.Параметры.ОстатокПолуч = ОстатокПолучатель;
                // Далее выводится строка в печатную форму


Работает, но долго, особенно если перемещение большое.
Потом оптимизировал его до такого вида:
                Запрос = Новый Запрос;
        Запрос.Текст =           
            "ВЫБРАТЬ
            |    ОстаткиТоваровКомпанииОстатки.Номенклатура,
            |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
            |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток
            |ИЗ
            |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки КАК ОстаткиТоваровКомпанииОстатки
            |ГДЕ
            |    ОстаткиТоваровКомпанииОстатки.Номенклатура = &Номенклатура
            |    И (ОстаткиТоваровКомпанииОстатки.СкладКомпании = &СкладКомпанииОтпр
            |    ИЛИ ОстаткиТоваровКомпанииОстатки.СкладКомпании = &СкладКомпанииПолуч)
            |
            |СГРУППИРОВАТЬ ПО
            |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
            |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток,
            |    ОстаткиТоваровКомпанииОстатки.Номенклатура";

        Запрос.УстановитьПараметр("Номенклатура", СтрокаТабличнойЧасти.Номенклатура);        
        Запрос.УстановитьПараметр("СкладКомпанииОтпр", ЭтотОбъект.СкладКомпании);
        Запрос.УстановитьПараметр("СкладКомпанииПолуч", ЭтотОбъект.СкладПолучатель);

        Выборка = Запрос.Выполнить().Выбрать();
        ОстатокНаСкладе = 0;
        Пока Выборка.Следующий() Цикл    
            Если Выборка.СкладКомпании = ЭтотОбъект.СкладКомпании Тогда
                ОстатокНаСкладе = Выборка.КоличествоОстаток;
            ИначеЕсли Выборка.СкладКомпании = ЭтотОбъект.СкладПолучатель Тогда
                ОстатокПолучатель = Выборка.КоличествоОстаток;
            КонецЕсли;
        КонецЦикла;
        ОбластьТовар.Параметры.Остаток = ОстатокНаСкладе;  
        ОбластьТовар.Параметры.ОстатокПолуч = ОстатокПолучатель;
                // Далее выводится строка в печатную форму


Время формирования печатной формы сократилось, но все-равно долго.

Подскажите пожалуйста, возможно-ли оптимизировать запрос еще, чтобы он не выполнялся каждый раз для каждой строки табличной части, а выполнился один раз для всего товара табличной части и двух складов, а разбор результата уже произвести в цикле?
Можно-ли позиции табличной части поместить в список и передать этот список в запрос в качестве параметра или саму табличную часть передать как параметр?

С Уважением, Дмитрий.
sava1
Все условия в параметры ВТ, группировку убрать

+ номенклатуру сразу всю в запрос

СпЗначений = ТаблЧасть.Выгрузить(,"Номенклатура");
....
...УстановитьПараметр("СпНоменклатура",СпЗначений);

в запросе Номенклатура в (&СпНоменклатура)
bizisoft
Цитата(sava1 @ 02.02.16, 11:29) необходимо зарегистрироваться для просмотра ссылки
Все условия в параметры ВТ, группировку убрать

Можно уточнить ВТ это временная таблица или что-то другое?
sava1
ВТ это виртуальная таблица (Остатков/оборотов)
Petre
Запрос.УстановитьПараметр("Номенклатура", СтрокаТабличнойЧасти.Номенклатура);

Вы же не в цикле такой запрос делаете?
bizisoft
Цитата(Petre @ 02.02.16, 12:00) необходимо зарегистрироваться для просмотра ссылки
Вы же не в цикле такой запрос делаете?

Понимаю, что 47067070.gif , поэтому и решил оптимизировать его, т.к. когда срочно реализовывал хотелку 09000000.gif , ничего другого в голову не пришло 64000000.gif
bizisoft
Все прекрасно получилось.
Выкладываю свой запрос:
    ...
    МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ОстаткиТоваровКомпанииОстатки.Номенклатура,
        |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
        |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток
        |ПОМЕСТИТЬ ОстОтпрПолуч
        |ИЗ
        |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки КАК ОстаткиТоваровКомпанииОстатки
        |ГДЕ
        |    ОстаткиТоваровКомпанииОстатки.Номенклатура В(&СпНоменклатура)
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ОстОтпрПолуч.Номенклатура,
        |    ОстОтпрПолуч.СкладКомпании,
        |    ОстОтпрПолуч.КоличествоОстаток
        |ИЗ
        |    ОстОтпрПолуч КАК ОстОтпрПолуч
        |ГДЕ
        |    ОстОтпрПолуч.СкладКомпании = &СкладОтпр
        |    ИЛИ ОстОтпрПолуч.СкладКомпании = &СкладПолуч";
    СпЗначений = ВыборкаТабличнойЧасти.Выгрузить(,"Номенклатура");     // Помещаем табл.часть в список
    Запрос.УстановитьПараметр("СпНоменклатура", СпЗначений);        // Передаем список в качестве параметра
    Запрос.УстановитьПараметр("СкладОтпр", ЭтотОбъект.СкладКомпании);    // Отбор по складу отправителю
    Запрос.УстановитьПараметр("СкладПолуч", ЭтотОбъект.СкладПолучатель);// и складу получателю    
    ВыборкаОстатков = Запрос.Выполнить().Выбрать();
    // Выгружаю в ТЗ результат выборки для дальнейшего поиска в цикле перебора ТЧ номенклатуры
    ВыбОст = Новый ТаблицаЗначений;
    ВыбОст.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура") );
    ВыбОст.Колонки.Добавить("ОстатокСкладОтправитель", Новый ОписаниеТипов("Число") );
    ВыбОст.Колонки.Добавить("ОстатокСкладПолучатель", Новый ОписаниеТипов("Число") );
    ВыбОст.Очистить(); // Очищаем Табл.Знач. от мусора    
    Пока ВыборкаОстатков.Следующий() Цикл
        НоваяСтрока = ВыбОст.Добавить();
        НоваяСтрока.Номенклатура = ВыборкаОстатков.Номенклатура;
        Если ВыборкаОстатков.СкладКомпании = ЭтотОбъект.СкладКомпании Тогда
            НоваяСтрока.ОстатокСкладОтправитель = ВыборкаОстатков.КоличествоОстаток;
            НоваяСтрока.ОстатокСкладПолучатель = 0;
        ИначеЕсли ВыборкаОстатков.СкладКомпании = ЭтотОбъект.СкладПолучатель Тогда
            НоваяСтрока.ОстатокСкладОтправитель = 0;
            НоваяСтрока.ОстатокСкладПолучатель = ВыборкаОстатков.КоличествоОстаток;                                          
        КонецЕсли;          
    КонецЦикла;    
    ВыбОст.Свернуть("Номенклатура","ОстатокСкладОтправитель, ОстатокСкладПолучатель");      
    // Перебираем табличную часть перемещения и формируем строки для вывода на печать
    Для Каждого СтрокаТабличнойЧасти Из ВыборкаТабличнойЧасти Цикл        
        ...
        ОбластьТовар.Параметры.ТоварНаименование = СтрокаТабличнойЧасти.Номенклатура.Наименование;
        // Поиск текущего товара в ТЗ с остатками        
        НайденаСтрока = ВыбОст.Найти(СтрокаТабличнойЧасти.Номенклатура, "Номенклатура");
        ОстатокНаСкладе =0;
        ОстатокПолучатель=0;
        Если НайденаСтрока = Неопределено Тогда
            Сообщить("НЕ НАЙДЕНО");
        Иначе
            ОстатокНаСкладе   = НайденаСтрока.ОстатокСкладОтправитель;
            ОстатокПолучатель = НайденаСтрока.ОстатокСкладПолучатель;
        КонецЕсли;         
        ОбластьТовар.Параметры.Остаток = ОстатокНаСкладе;  
        ОбластьТовар.Параметры.ОстатокПолуч = ОстатокПолучатель;
        ...
           ТабличныйДокумент.Вывести(ОбластьТовар);            
    КонецЦикла;    
    МенеджерВременныхТаблиц.Закрыть();  // Удаление ВременнойТаблицы


Взял для сравнения Перемещение на 52 строки, нажал Печать и начал отсчет (без секундомера), так на вскидку 1, 2, 3 ...
От момента нажатия Печать и до Появления печатной формы получилось:
До оптимизации - 26 с или 0,5с/строку
После оптимизации - 2 с или 0,038с/строку.

Всем Большое спасибо за помощь.
Zaval
Цитата(bizisoft @ 02.02.16, 14:26) необходимо зарегистрироваться для просмотра ссылки
так на вскидку 1, 2, 3 ...

Оффтоп. smile.gif
Если говорить вслух - это будет по полсекунды. Чтобы получились секунды, надо считать "21, 22, 23".
sava1
Да - оптимизация "офигеть".
Жаль - нет внешних источников, АДО и остальных примочек.
Petre
Запрос.Текст = 
        "ВЫБРАТЬ
        |    ОстаткиТоваровКомпанииОстатки.Номенклатура,
        |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
        |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток
        |ИЗ
        |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки(
        |            ,
        |            Номенклатура В (&СпНоменклатура)
        |                И СкладКомпании В (&СкладОтпр, &СкладПолуч)) КАК ОстаткиТоваровКомпанииОстатки";
sava1
Да здесь надо бы еще ИТОГИ показать человеку и Параметры.Заполнить...(строкаВыборки);
bizisoft
Цитата(Zaval @ 02.02.16, 15:32) необходимо зарегистрироваться для просмотра ссылки
Если говорить вслух - это будет по полсекунды. Чтобы получились секунды, надо считать "21, 22, 23".

Если быть точным, то дело было так: "и-и раз", "и-и два", "и-и три" rulez.gif

Цитата(Petre @ 02.02.16, 15:40) необходимо зарегистрироваться для просмотра ссылки
Запрос.Текст =         "ВЫБРАТЬ
        |    ОстаткиТоваровКомпанииОстатки.Номенклатура,
        |    ОстаткиТоваровКомпанииОстатки.СкладКомпании,
        |    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток
        |ИЗ
        |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки(
        |            ,
        |            Номенклатура В (&СпНоменклатура)
        |                И СкладКомпании В (&СкладОтпр, &СкладПолуч)) КАК ОстаткиТоваровКомпанииОстатки";


Я правильно понимаю этот запрос получает, тоже самое что и мой, только без временной таблицы? upset.gif


sava1
Да - это оптимальный запрос.

+ если в выборку добавить ИТОГИ - не надо будет сворачивать таблицу, а если колонки назвать так-же как Параметры,
то не надо прописывать заполнение параметров по-отдельности.
bizisoft
sava1 @ Сегодня, 16:29 необходимо зарегистрироваться для просмотра ссылки,
А можете пояснить вот эту запись, а то не совсем понятно.
Если с Номенклатура В (&СпНоменклатура) и СкладКомпании В (&СкладОтпр, &СкладПолуч) как бы понятно, то что означает запятая какой-то пустой параметр?

        |    РегистрНакопления.ОстаткиТоваровКомпании.Остатки(
        |            ,
        |            Номенклатура В (&СпНоменклатура)
        |                И СкладКомпании В (&СкладОтпр, &СкладПолуч)) КАК ОстаткиТоваровКомпанииОстатки";
sava1
Первый параметр - Дата остатков. Если пустая - значит берем актуальные значения.
bizisoft
sava1 @ Сегодня, 16:41 необходимо зарегистрироваться для просмотра ссылки,
Век живи - век учись.
А я тут чешу левое ухо правой рукой через голову crazy.gif .
Мне остается только одно 32542620.gif

P.S. Одно радует научился работать в ВТ 433.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.