Архив за месяц: Январь 2015

1C 7.7. Прямой запрос с группировкой без индексированной таблицы

Прямые запросы в 1С++ — это отличный способ в тысячи раз ускорить выборки данных по сравнению со стандартными запросами 1С 7.7. Особенно полезно для крупных баз, свыше 100Гб, где требуется оптимизация. Группировка индексной таблицей — это дополнительные затраты серверного ресурса, и порой долгие минуты ожидания для пользователя. Запросы с использованием ROLLUP позволят получать данные с итогами по группировкам уже в самом запросе.

К примеру, получим остатки.

ТекстЗапроса = "SELECT
|тмц [ТМЦ $Справочник.ТМЦ]
|,Партия [Партия $Справочник.Партии]
|,GROUPING(ТМЦ) AS ИтогПоТоварам 
|,GROUPING(Партия) AS ИтогПоПартиям
|,MAX(Склад) [Склад $Справочник.Склады]
|,MAX($спрТМЦ.БазЕдиница) [БазЕдиница $Перечисление.Единицы]
|,sum(КвоОстаток) as количество
|FROM
|$РегистрОстатки.Остатки(:ДатаПо~
|,
|,ВидУчета = :выбВидУчета
|,(ТМЦ,Партия,Склад)) AS ОстаткиТМЦ
|LEFT JOIN $Справочник.ТМЦ AS спрТМЦ
|ON ОстаткиТМЦ.ТМЦ = спрТМЦ.ID
|group BY ТМЦ,Партия WITH ROLLUP
|HAVING SUM(КвоОстаток) > 0
|ORDER BY ТМЦ,Партия,MAX(Склад), SUM(КвоОстаток) DESC";

Как видно из запроса, мы создаем две группы: ТМЦ и Партия.

Теперь поля приобртают значение в зависимости от уровня группировки: ИтогПоТоварам =1 и ИтогПоПартиям = 1 ,  — это общий итог.

ИтогПоТоварам =0 и ИтогПоПартиям = 1 , когда попадаем на строку с итогом по товару, куда «всуммировались» и итоги по каждой партии отдельно

ИтогПоТоварам =0 и ИтогПоПартиям = 0 , когда попадаем на строку с итогом по партии, который в свою очередь находится внутри итога по товару. Они же детальные строки.

Как можно использовать это?

Смотрим пример обхода результата выборки.

Запрос.УстановитьТекстовыйПараметр("ДатаПо",ДатаПо);
Запрос.УстановитьТекстовыйПараметр("выбВидУчета",выбВидУчета);
тз = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
//тз.выбратьСтроку();

ТабДок = СоздатьОбъект("Таблица");

КолВоСтрок = тз.КоличествоСтрок();
табДок = СоздатьОбъект("таблица")    ;
табДок.ИсходнаяТаблица("таблица");
.....

тз.ВыбратьСтроки();
нппТовар = 1;
нппПартия=1;
Пока тз.ПолучитьСтроку()=1 Цикл
 Если (тз.ИтогПоТоварам=1) И (тз.ИтогПоПартиям=1) Тогда
  Количество = тз.Количество;
  ТабДок.ВывестиСекцию ("Итого");
  нппПартия=1;
ИначеЕсли (тз.ИтогПоТоварам=0) И (тз.ИтогПоПартиям=1) Тогда
  ТМЦ = тз.ТМЦ;
  Количество = тз.Количество;
  ТабДок.ВывестиСекцию ("СтрокаТовара");
  нппТовар=нппТовар+1;
  нппПартия=1;
 ИначеЕсли тз.ИтогПоПартиям=0 тогда
  Партия = тз.Партия;
  Количество = тз.Количество;
  Склад = ТЗ.Склад;
  БазЕдиница = ТЗ.БазЕдиница;
  ТабДок.ВывестиСекцию ("СтрокаПартии");
  нппПартия=нппПартия+1;
 КонецЕсли;
 нпп=нпп+1;
 проц = Окр(нпп/КолВоСтрок*100,1,1);
 Состояние ("Вывод отчета "+Строка(проц)+"%");
КонецЦикла;

Ну и результат, привычно для отчетов, которые любят в 1С 8.х — когда итоги размещаются сверху групп, их не надо суммировать в переменные, или группировать в индексированной таблице. Всё выводится очень быстро и естественно.

 

Желаю удачи!