Как указать условие в периоде виртуальной таблицы 1С

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При работе с виртуальными таблицами в языке запросов 1С (например, Хозрасчетный.Обороты) разработчики часто сталкиваются с необходимостью динамически вычислять границы периода. Попытка вставить условную конструкцию ВЫБОР КОГДА ... КОНЕЦ или функцию МАКСИМУМ непосредственно в параметры виртуальной таблицы НачалоПериода и КонецПериода приводит к ошибке синтаксиса.

Рассмотрим, почему возникают ограничения платформы и как правильно реализовать подобную логику в коде конфигурации.

Причины возникновения ошибки

Проанализируем механику работы виртуальных таблиц в платформе 1С. Параметры периода виртуальных таблиц служат для построения оптимизированных SQL-запросов к СУБД. В силу особенностей архитектуры платформа накладывает жесткие ограничения на выражения, допустимые в параметрах НачалоПериода и КонецПериода:

  1. Запрет сложных конструкций: В параметрах виртуальных таблиц запрещено использовать конструкцию ВЫБОР, агрегатные функции (МАКСИМУМ, МИНИМУМ), подзапросы и соединения. Допускаются только простые параметры запроса, конкретные значения типа Дата, а также базовые функции НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА и ДОБАВИТЬКДАТЕ.
  2. Проверка корректности интервала дат: При выполнении запроса платформа проверяет, чтобы дата начала периода не превышала дату окончания. Если условная математика с датами приводит к тому, что дата конца оказывается меньше даты начала (например, вычитание месяца в январе возвращает декабрь прошлого года), запрос завершается ошибкой даже внутри ветки ОБЪЕДИНИТЬ ВСЕ.

Способ 1. Вычисление параметров на стороне встроенного языка (рекомендуемый)

Наиболее эффективным и правильным подходом является вынос логики расчета границ периода из текста запроса в код 1С. Рассчитаем значения дат до передачи параметров в объект Запрос.

Разберем по шагам реализацию данного подхода:

  1. Определим логику проверки месяца на языке 1С.
  2. Рассчитаем точные даты начала и окончания периода.
  3. Передадим полученные значения в параметры запроса &ДатаНачалаПериода и &ДатаОкончанияПериода.

Посмотрим на пример кода:


// Расчет дат на стороне 1С
Если Месяц(УказаннаяДата) = 1 Тогда
    ДатаНачала = НачалоГода(УказаннаяДата);
    ДатаОкончания = КонецДня(НачалоГода(УказаннаяДата));
Иначе
    ДатаНачала = НачалоГода(УказаннаяДата);
    ДатаОкончания = КонецМесяца(ДобавитьМесяц(УказаннаяДата, -1));
КонецЕсли;

// Передача параметров в запрос
Запрос.УстановитьПараметр("ДатаНачалаПериода", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончанияПериода", ДатаОкончания);

В самом тексте запроса параметр периода виртуальной таблицы указывается максимально просто:


ВЫБРАТЬ
    РегистрОбороты.Счет КАК Счет,
    РегистрОбороты.СуммаОборотДт КАК СуммаОборотДт
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Обороты(&ДатаНачалаПериода, &ДатаОкончанияПериода, , , , , , ) КАК РегистрОбороты

Способ 2. Динамическое формирование текста запроса

Если алгоритм выполняется в служебных модулях (например, при формировании проводок в процедурах вида ТекстОтраженияВРеглУчете() в 1С:ERP), текст запроса формируется программно. В этом случае условный оператор Если ... Тогда проверяется в коде модуля, а в сам текст запроса подставляется нужный фрагмент.

Рассмотрим пример генерации текста:


Если Месяц(ПараметрыОтражения.Дата) = 1 Тогда
    ТекстВыраженияПериода = "НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ)";
Иначе
    ТекстВыраженияПериода = "КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата, МЕСЯЦ, -1), МЕСЯЦ)";
КонецЕсли;

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

Способ 3. Использование физической таблицы движения регистра

Если условие обязательно должно вычисляться полностью внутри запроса без предварительной установки параметров из кода, можно отказаться от применения виртуальной таблицы и обратиться напрямую к реальной (физической) таблице движений.

В секции ГДЕ реальной таблицы платформой разрешено использовать конструкции ВЫБОР КОГДА и сложные функции работы с датами. При этом необходимо явно прописать группировку и суммирование ресурсов.

Проанализируем пример такого запроса:


ВЫБРАТЬ
    Движения.СчетДт КАК Счет,
    СУММА(Движения.Сумма) КАК СуммаОборотДт
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК Движения
ГДЕ
    Движения.Период МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ГОД) И 
        ВЫБОР 
            КОГДА МЕСЯЦ(&Дата) = 1 
                ТОГДА КОНЕЦПЕРИОДА(НАЧАЛОПЕРИОДА(&Дата, ГОД), ДЕНЬ)
            ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата, МЕСЯЦ, -1), МЕСЯЦ)
        КОНЕЦ
СГРУППИРОВАТЬ ПО
    Движения.СчетДт

Важно: Обращение к физической таблице может уступать по производительности виртуальным таблицам на больших объемах данных, поэтому данный метод стоит использовать только при отсутствии возможности рассчитать параметры в коде 1С.

← На главную