четверг, 2 октября 2014 г.

Использование менеджера временных таблиц в запросах

Использование менеджера временных таблиц весьма эфективно при больших объемах данных.




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

Важным есть удаление временных таблиц и закрытие менеджера временных таблиц.

МенВрТаб = Новый МенеджерВременныхТаблиц;

   
Счет6202 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("62.02");
   
Счет76АВ = ПланыСчетов.Хозрасчетный.НайтиПоКоду("76.АВ");

//->запрос ищет основные проблемные контрагенты и документы расчетов
   
ТекстЗапроса = "ВЫБРАТЬ
    |   &Счет76АВ КАК СчетДт,
    |   &Счет6202 КАК СчетКт,
    |   ЕСТЬNULL(Остатки6202.Субконто1, Остатки76АВ.Субконто1) КАК Контрагент,
    |   ЕСТЬNULL(Остатки6202.Субконто3, Остатки76АВ.Субконто2) КАК ДокументРасчетов,
    |   ЕСТЬNULL(ВЫРАЗИТЬ(Остатки6202.СуммаОстатокКт / 118 * 18 КАК ЧИСЛО(15, 2)), 0) КАК РасчетнаяСумма,
    |   ЕСТЬNULL(Остатки76АВ.СуммаОстатокДт, 0) КАК СуммаОстатокДт,
    |   ЕСТЬNULL(Остатки6202.СуммаОстатокКт, 0) КАК СуммаОстатокКт
    |ПОМЕСТИТЬ ВремТаблРасхождения
    |ИЗ
    |   РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаАнализа, Счет = &Счет6202, , Организация = &Организация) КАК Остатки6202
    |       ПОЛНОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаАнализа, Счет = &Счет76АВ, , Организация = &Организация) КАК Остатки76АВ
    |       ПО Остатки6202.Субконто1 = Остатки76АВ.Субконто1
    |           И Остатки6202.Субконто3 = Остатки76АВ.Субконто2
    |ГДЕ
    |   ВЫБОР
    |           КОГДА ЕСТЬNULL(Остатки6202.СуммаОстатокКт, 0) > 0
    |                   И (ВЫРАЗИТЬ(Остатки6202.СуммаОстатокКт / 118 * 18 КАК ЧИСЛО(15, 2))) <> ЕСТЬNULL(Остатки76АВ.СуммаОстатокДт, 0)
    |               ТОГДА ИСТИНА
    |           КОГДА ЕСТЬNULL(Остатки6202.СуммаОстатокКт, 0) = 0
    |                   И ЕСТЬNULL(Остатки76АВ.СуммаОстатокДт, 0) > 0
    |               ТОГДА ИСТИНА
    |           КОГДА ЕСТЬNULL(Остатки6202.СуммаОстатокКт, 0) < 0
    |                   И ЕСТЬNULL(Остатки76АВ.СуммаОстатокДт, 0) = 0
    |               ТОГДА ИСТИНА
    |           ИНАЧЕ ЛОЖЬ
    |       КОНЕЦ
    |
    |ИНДЕКСИРОВАТЬ ПО
    |   Контрагент,
    |   ДокументРасчетов"
;

   
Запрос = Новый Запрос();
   
Запрос.УстановитьПараметр("ДатаАнализа", Новый Граница(КонецДня(ДатаАнализа), ВидГраницы.Включая));
   
Запрос.УстановитьПараметр("Организация", Организация);
   
Запрос.УстановитьПараметр("Счет6202", Счет6202);
   
Запрос.УстановитьПараметр("Счет76АВ", Счет76АВ);

   
Запрос.МенеджерВременныхТаблиц = МенВрТаб;

   
Запрос.Текст = ТекстЗапроса;
   
Запрос.Выполнить(); //<-
   
ОсновнойМенВрТаб = Запрос.МенеджерВременныхТаблиц; //сохраняем ссылку на основную таблицу менеджера
   
ТабличноеПоле.Очистить();

   
//-> обходим периоды в цикле пытаясь найти все проблемные периоды

   
ЕщеЕстьРасхождения = Истина;
   
РасчетнаяДата = ДатаАнализа;

    Пока
ЕщеЕстьРасхождения Цикл

       
ОбработкаПрерыванияПользователя();

       
ЗапросПериоды = Новый Запрос;
       
ЗапросПериоды.Текст = "ВЫБРАТЬ
        |   ДанныеСчетов.Контрагент,
        |   ДанныеСчетов.ДокументРасчетов,
        |   СУММА(ДанныеСчетов.КонечныйОстатокКт) КАК КонечныйОстатокКт,
        |   СУММА(ДанныеСчетов.КонечныйОстатокДт) КАК КонечныйОстатокДт
        |ПОМЕСТИТЬ ОстаткиПоСчетам
        |ИЗ
        |   (ВЫБРАТЬ
        |       Остатки6202.Субконто1 КАК Контрагент,
        |       Остатки6202.Субконто3 КАК ДокументРасчетов,
        |       ВЫРАЗИТЬ(Остатки6202.СуммаОстатокКт / 118 * 18 КАК ЧИСЛО(15, 2)) КАК КонечныйОстатокКт,
        |       0 КАК КонечныйОстатокДт
        |   ИЗ
        |       РегистрБухгалтерии.Хозрасчетный.Остатки(
        |               &ДатаАнализа,
        |               Счет = &Счет6202,
        |               ,
        |               Организация = &Организация
        |                   И Субконто1 В
        |                       (ВЫБРАТЬ
        |                           ВремТаблРасхождения.Контрагент
        |                       ИЗ
        |                           ВремТаблРасхождения КАК ВремТаблРасхождения)
        |                   И Субконто3 В
        |                       (ВЫБРАТЬ
        |                           ВремТаблРасхождения.ДокументРасчетов
        |                       ИЗ
        |                           ВремТаблРасхождения КАК ВремТаблРасхождения)) КАК Остатки6202
        |
        |   ОБЪЕДИНИТЬ ВСЕ
        |
        |   ВЫБРАТЬ
        |       Остатки76АВ.Субконто1,
        |       Остатки76АВ.Субконто2,
        |       0,
        |       Остатки76АВ.СуммаОстатокДт
        |   ИЗ
        |       РегистрБухгалтерии.Хозрасчетный.Остатки(
        |               &ДатаАнализа,
        |               Счет = &Счет76АВ,
        |               ,
        |               Организация = &Организация
        |                   И Субконто1 В
        |                       (ВЫБРАТЬ
        |                           ВремТаблРасхождения.Контрагент
        |                       ИЗ
        |                           ВремТаблРасхождения КАК ВремТаблРасхождения)
        |                   И Субконто2 В
        |                       (ВЫБРАТЬ
        |                           ВремТаблРасхождения.ДокументРасчетов
        |                       ИЗ
        |                           ВремТаблРасхождения КАК ВремТаблРасхождения)) КАК Остатки76АВ) КАК ДанныеСчетов
        |
        |СГРУППИРОВАТЬ ПО
        |   ДанныеСчетов.Контрагент,
        |   ДанныеСчетов.ДокументРасчетов
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |УНИЧТОЖИТЬ ВремТаблРасхождения
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |   ОстаткиПоСчетам.Контрагент КАК Контрагент,
        |   ОстаткиПоСчетам.ДокументРасчетов КАК ДокументРасчетов,
        |   ОстаткиПоСчетам.КонечныйОстатокКт,
        |   ОстаткиПоСчетам.КонечныйОстатокДт
        |ПОМЕСТИТЬ ВремТаблРасхождения
        |ИЗ
        |   ОстаткиПоСчетам КАК ОстаткиПоСчетам
        |ГДЕ
        |   ВЫБОР
        |           КОГДА ОстаткиПоСчетам.КонечныйОстатокКт < 0
        |                   И ОстаткиПоСчетам.КонечныйОстатокДт = 0
        |               ТОГДА ЛОЖЬ
        |           КОГДА ОстаткиПоСчетам.КонечныйОстатокКт <> ОстаткиПоСчетам.КонечныйОстатокДт
        |               ТОГДА ИСТИНА
        |           ИНАЧЕ ЛОЖЬ
        |       КОНЕЦ
        |
        |ИНДЕКСИРОВАТЬ ПО
        |   Контрагент,
        |   ДокументРасчетов
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |   &Период,
        |   ОстаткиПоСчетам.Контрагент,
        |   ОстаткиПоСчетам.ДокументРасчетов
        |ИЗ
        |   ОстаткиПоСчетам КАК ОстаткиПоСчетам
        |ГДЕ
        |   (ОстаткиПоСчетам.КонечныйОстатокКт = ОстаткиПоСчетам.КонечныйОстатокДт
        |           ИЛИ ВЫБОР
        |               КОГДА ОстаткиПоСчетам.КонечныйОстатокКт < 0
        |                       И ОстаткиПоСчетам.КонечныйОстатокДт = 0
        |                   ТОГДА ИСТИНА
        |               ИНАЧЕ ЛОЖЬ
        |           КОНЕЦ)
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |УНИЧТОЖИТЬ ОстаткиПоСчетам"
;


       
РасчетнаяДата = НачалоМесяца(РасчетнаяДата)-1;

       
ЗапросПериоды.УстановитьПараметр("Период", КонецДня(РасчетнаяДата)+1);
       
ЗапросПериоды.УстановитьПараметр("ДатаАнализа", Новый Граница(КонецДня(РасчетнаяДата), ВидГраницы.Включая));
       
ЗапросПериоды.УстановитьПараметр("Организация", Организация);
       
ЗапросПериоды.УстановитьПараметр("Счет6202", Счет6202);
       
ЗапросПериоды.УстановитьПараметр("Счет76АВ", Счет76АВ);

       
ЗапросПериоды.МенеджерВременныхТаблиц = ОсновнойМенВрТаб;

       
Рез = ЗапросПериоды.ВыполнитьПакет();

       
ЕщеЕстьРасхождения = Булево(Рез.Получить(2).Выгрузить().Получить(0).Количество>0); //[ВремТаблРасхождения] таблица уменшается при переходящем периоде.
       
Таблица = Рез.Получить(3).Выгрузить(); //таблица найденных ПРОБЛЕМНЫХ периодов (к этому периоду прибавлен месяц и это будет проблемный месяц)

       
Для Каждого Выборка Из Таблица Цикл

           
НоваяСтрока = ТабличноеПоле.Добавить();
           
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);

        КонецЦикла;

       
ОсновнойМенВрТаб = ЗапросПериоды.МенеджерВременныхТаблиц;

    КонецЦикла;
//<-
    //->уничтожаем временну таблицу и закрываем менеджер!
   
УдалениеМенеджераВТ = Новый Запрос();
   
УдалениеМенеджераВТ.МенеджерВременныхТаблиц = ОсновнойМенВрТаб;

   
УдалениеМенеджераВТ.Текст = "УНИЧТОЖИТЬ ВремТаблРасхождения";
   
УдалениеМенеджераВТ.Выполнить();

   
ОсновнойМенВрТаб.Закрыть(); //<- 

Вывод результата менеджера временных таблиц в таблицу значений (отладка данных МВТ)

Иногда предстоит отлаживать запросы которые содержат менеджеры временных таблиц. И чтобы увидеть результат менеджера необходим еще один запрос к этому менеджеру. Пример функции которая выводит результат менеджера в таблицу значений:


Функция ВывестиРезультатМенеджераВременныхТаблиц(МенеджерВременныхТаблиц, ИмяТаблицы) Экспорт

   
//Получаем таблицу из менеджера временных таблиц запроса
   
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ "+ИмяТаблицы);
   
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;

    Возврат
Запрос.Выполнить().Выгрузить();
КонецФункции

Вывод дополнительных полей МВТ.

Подобная функция, только в третий параметр передаются дополнительные поля. При необходимости увидеть для целей отладки какой-то реквизит после точки.
В параметр ДополнительныеПоля передаем например "Номенклатура.Поставщик, Номенклатура.Менеджер" и т.д.

Функция ВывестиРезультатМенеджераВременныхТаблиц(МенеджерВременныхТаблиц, ИмяТаблицы, ДополнительныеПоля="") Экспорт

   
//Получаем таблицу из менеджера временных таблиц запроса
   
Запрос = Новый Запрос("ВЫБРАТЬ *"+?(Не ПустаяСтрока(ДополнительныеПоля), ", "+ДополнительныеПоля, "")+" ИЗ "+ИмяТаблицы);
   
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;

    Возврат
Запрос.Выполнить().Выгрузить();
КонецФункции





1 комментарий:

  1. Этот комментарий был удален администратором блога.

    ОтветитьУдалить