Как вычислить минимальную дату в ресурсе СКД, исключая пустые значения

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

При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда в наборе данных присутствуют пустые даты (значение 01.01.0001). Если для такого поля в ресурсах просто указать агрегатную функцию Минимум(ДатаПрибытия), результат всегда будет равен пустой дате, если в выборке есть хотя бы одна незаполненная строка. Это происходит потому, что 01.01.0001 — это минимально возможное значение типа Дата в 1С. В данной статье мы подробно разберем, как правильно отсечь пустые значения при расчете итогов, и рассмотрим несколько эффективных способов решения этой задачи.

Механизм обработки NULL в агрегатных функциях СКД

Прежде чем перейти к конкретным формулам, давайте проанализируем, как работают агрегатные функции в СКД (такие как СУММА, МИНИМУМ, МАКСИМУМ). Важной особенностью системы компоновки данных является то, что агрегатные функции автоматически игнорируют значения NULL. Это фундаментальное свойство мы и будем использовать для решения нашей задачи. Если мы подменим пустую дату на NULL в процессе вычисления ресурса, СКД просто «не заметит» эти строки при поиске минимального значения.

Способ 1. Использование конструкции ВЫБОР в выражении ресурса

Рассмотрим самый распространенный и быстрый способ. Нам необходимо изменить выражение в колонке «Выражение» на закладке «Ресурсы». Вместо простого обращения к полю, мы напишем логическое условие. Разберем по шагам, как это выглядит:

Для начала используем проверку на соответствие пустой дате через ДАТАВРЕМЯ(1, 1, 1). Выражение будет выглядеть следующим образом:


МИНИМУМ(ВЫБОР 
    КОГДА ДатаПрибытия = ДАТАВРЕМЯ(1, 1, 1) 
    ТОГДА NULL 
    ИНАЧЕ ДатаПрибытия 
КОНЕЦ)

Почему это работает? Рассмотрим логику выполнения:

  1. Система перебирает все строки, входящие в группировку.
  2. Для каждой строки проверяется условие: является ли дата пустой.
  3. Если дата пустая, выражение внутри функции МИНИМУМ возвращает NULL.
  4. Если дата заполнена, возвращается само значение даты.
  5. Функция МИНИМУМ собирает все полученные значения, выбрасывает из них NULL и среди оставшихся реальных дат находит самую раннюю.

Способ 2. Использование функции ЗначениеЗаполнено

Этот метод является более современным и наглядным. Проанализируем ситуацию: в СКД выражения ресурсов вычисляются программным процессором компоновки, а это значит, что нам доступны многие функции встроенного языка 1С, которые недоступны в обычных запросах к СУБД. Одной из таких функций является ЗначениеЗаполнено().

Выясним, как упростить наше выражение:

Минимум(Выбор Когда ЗначениеЗаполнено(ДатаПрибытия) Тогда ДатаПрибытия Конец)

Обратите внимание, что в данном примере мы даже не пишем явное ИНАЧЕ NULL. В языке выражений СКД, если условие КОГДА не выполняется и ветка ИНАЧЕ отсутствует, конструкция ВЫБОР по умолчанию возвращает NULL. Это делает код ресурса компактным и легким для чтения. Кроме того, ЗначениеЗаполнено универсальна — если тип поля в будущем изменится, логика проверки на «пустоту» останется корректной.

Способ 3. Вычисляемые поля для предварительной очистки данных

Иногда логику проверки удобно вынести за пределы ресурсов. Это полезно, если вы планируете использовать «чистую» дату в нескольких местах (например, в разных ресурсах или для вывода в детальных записях). Посмотрим, как это реализовать через Вычисляемые поля:

  1. Переходим на закладку Вычисляемые поля.
  2. Добавляем новое поле, назовем его ДатаПрибытияДляИтогов.
  3. В поле «Выражение» вписываем: ВЫБОР КОГДА ЗначениеЗаполнено(ДатаПрибытия) ТОГДА ДатаПрибытия ИНАЧЕ NULL КОНЕЦ.
  4. Теперь на закладке Ресурсы мы можем использовать простое выражение: Минимум(ДатаПрибытияДляИтогов).

Этот подход позволяет избежать дублирования сложного кода ВЫБОР...КОНЕЦ, если вам нужно посчитать и минимум, и максимум, и среднее значение по одному и тому же правилу фильтрации.

Способ 4. Использование функции ВычислитьВыражениеСГруппировкойМассив

Рассмотрим более сложный сценарий, который упоминался в обсуждении. Существует мощная функция ВычислитьВыражениеСГруппировкойМассив. Она позволяет собрать значения из группировок в массив и применить к ним отбор. Хотя для простой задачи поиска минимума этот метод может быть избыточным (и более медленным), его полезно знать для сложных расчетов.

Синтаксис функции с отбором выглядит так:


Минимум(ВычислитьВыражениеСГруппировкойМассив("ДатаПрибытия", "ДатаПрибытия", "ЗначениеЗаполнено(ДатаПрибытия)"))

Здесь третий параметр — это строка отбора. Система сначала отфильтрует данные по условию ЗначениеЗаполнено(ДатаПрибытия), затем соберет их в массив и только потом вычислит Минимум. Используйте этот метод только в том случае, если вам нужно выполнять агрегацию с учетом контекста других группировок, которые недоступны через обычный ВЫБОР. Для задач нестандартного объединения данных из строк пригодится способ сбора значений колонки из нескольких строк в СКД.

Обработка ситуации, когда все даты в выборке пустые

Проанализируем ситуацию: что произойдет, если отчет строится за период, в котором нет ни одной заполненной даты прибытия? В этом случае наше выражение Минимум(ВЫБОР...) вернет NULL. В ячейке отчета это будет выглядеть как пустота. Если при отсутствии данных требуется динамически убрать пустые столбцы, можно использовать прием скрытия колонок без данных в отчетах СКД.

Если бизнес-требования диктуют необходимость выводить в таких случаях какой-то текст или специальное значение, мы можем обернуть нашу функцию в ЕстьNULL. Рассмотрим пример:


ЕстьNULL(Минимум(Выбор Когда ЗначениеЗаполнено(ДатаПрибытия) Тогда ДатаПрибытия Конец), "Данные отсутствуют")

Такой подход делает отчет более профессиональным и понятным для конечного пользователя.

Советы по производительности

При работе с очень большими объемами данных (сотни тысяч и миллионы строк) вычисления в ресурсах СКД могут нагружать процессор сервера. Если вы заметили замедление формирования отчета, рекомендуется перенести логику замены пустых дат на NULL непосредственно в **Набор данных - запрос**.

В тексте запроса это будет выглядеть так:


ВЫБРАТЬ
    ВЫБОР КОГДА Таблица.ДатаПрибытия = ДАТАВРЕМЯ(1, 1, 1) ТОГДА NULL ИНАЧЕ Таблица.ДатаПрибытия КОНЕЦ КАК ДатаПрибытияЧистая
ИЗ
    ...

В этом случае СКД получит уже «подготовленные» данные, и выполнение агрегатной функции Минимум пройдет максимально быстро на уровне SQL-запроса.

Подведем итог: наиболее рекомендуемым и сбалансированным способом для большинства задач является использование конструкции Минимум(Выбор Когда ЗначениеЗаполнено(Поле) Тогда Поле Конец) непосредственно в настройках ресурсов СКД. Это гибко, наглядно и эффективно.

← На главную