При разработке отчетов в платформе 1С:Предприятие 7.7 нередко возникает задача получить в рамках одного запроса несколько разных числовых показателей с индивидуальными условиями. Например, требуется вывести в одной строке по каждой номенклатурной позиции остаток по основному складу и остаток по складу брака либо разделить суммы оборотов на прямые продажи и возвраты.
Для решения подобных задач в языке запросов 1С 7.7 предусмотрена специальная конструкция КОГДА (в англоязычном варианте WHEN), которая накладывает локальный фильтр исключительно на рассчитываемую агрегатную функцию.
Разберем базовый синтаксис объявления функции в тексте запроса платформы 1С 7.7:
Синтаксис:
Функция <ИмяФункции> = <ТипФункции>(<Параметр>) [Когда(<Условие>)];
Параметры конструкции:
КонОст, НачОст, Приход, Расход, Сумма, Счёт и др.Главное отличие конструкции КОГДА от секции Условие(...) заключается в области действия: секция Условие(...) фильтрует строки для всего запроса целиком, а условие в КОГДА применяется только к конкретной функции, не затрагивая остальные рассчитываемые показатели.
Рассмотрим типовые сценарии использования локальных условий в запросах.
1. Разделение остатков по группам складов:
Посмотрим на пример запроса, в котором по каждой позиции номенклатуры одновременно рассчитываются конечные остатки по двум разным спискам складов:
// Списки складов должны быть предварительно сформированы в модуле
ВыбСклад1 = СоздатьОбъект("СписокЗначений");
ВыбСклад2 = СоздатьОбъект("СписокЗначений");
// Заполнение списков элементами справочника Склады...
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = "
|Склад = Регистр.ОстаткиТоваров.Склад;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Количество = Регистр.ОстаткиТоваров.Количество;
|Функция КоличествоКонОст1 = КонОст(Количество) КОГДА (Склад В ВыбСклад1);
|Функция КоличествоКонОст2 = КонОст(Количество) КОГДА (Склад В ВыбСклад2);
|Группировка Товар без групп;
|Условие (Товар В ВыбТовар);
|";
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Пока Запрос.Группировка(1) = 1 Цикл
Сообщить(Строка(Запрос.Товар) + " | Склад 1: " + Запрос.КоличествоКонОст1 + " | Склад 2: " + Запрос.КоличествоКонОст2);
КонецЦикла;
КонецЕсли;
2. Разделение оборотов на продажи и возвраты:
Проанализируем пример, где по знаку количества расхода отсекаются возвраты покупателей:
ТекстЗапроса = "
|Товар = Регистр.Продажи.Товар;
|РасходКво = Регистр.Продажи.Количество;
|Функция РасходСумма = Сумма(РасходКво) КОГДА (РасходКво > 0);
|Функция РасходВозврат = Сумма(РасходКво) КОГДА (РасходКво < 0);
|Группировка Товар;
|";
3. Фильтрация по свойствам документов:
Посмотрим на пример отбора движений только по определенному виду документа:
ТекстЗапроса = "
|ТекДок = Регистр.Заказы.ТекущийДокумент;
|КолЗаказа = Регистр.Заказы.Количество;
|Функция ПолученоПок = Расход(КолЗаказа) КОГДА (ТекДок.Вид() <> ""ЗаказПоставщику"");
|Группировка ТекДок;
|";
Выясним причину, почему запрос с конструкцией КОГДА может выдавать одинаковые или неверные цифры во всех колонках.
Попытка вызвать пользовательскую функцию прямо внутри секции КОГДА, например: КОГДА (Склад В ВернутьСписокСкладов(...)), приводит к непредсказуемой работе парсера запросов 1С 7.7. Движок платформы вычисляет условие построчно для каждого движения, и повторный динамический возврат объектов может сбоить, вызывая утечки дескрипторов и искажение результата. Все списки значений и фильтры необходимо создавать до сборки текста запроса и обращаться к ним по имени переменной.
Если измерение регистра (например, Склад) имеет тип ссылки на справочник, то и список значений (СписокЗначений), передаваемый в оператор В, обязан содержать именно ссылки на элементы справочника, а не их строковые наименования или коды. При несовпадении типов условие всегда будет вычисляться как ложное либо игнорироваться.
Переменные списков значений (например, ВыбСклад1), передаваемые в условия запроса, должны быть инициализированы в той же области видимости (локальные переменные процедуры или переменные модуля формы/отчета) и существовать в памяти на момент вызова Запрос.Выполнить(...).
Следует учитывать, что при расчете КонОст без условий платформа 1С 7.7 берет готовые данные из таблицы итогов регистров. Добавление сложного условия в КОГДА заставляет движок перебирать записи таблицы движений, что на больших базах может заметно замедлить выполнение отчета. В таких случаях альтернативным решением является получение остатков в группировке по измерению с последующей обработкой в ТаблицеЗначений средствами встроенного языка.