Как определить дату первой продажи в СКД без вывода детальных записей?

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

При разработке отчетов на Системе компоновки данных (СКД) часто возникает задача: необходимо вывести в итогах по номенклатуре или складу дату самой первой продажи за выбранный период. Сложность заключается в том, что отчет зачастую должен оставаться компактным, и выводить группировку по дням (детальные записи) пользователю не требуется. Стандартный агрегат Минимум(Период) в ресурсах может работать некорректно, если в выборку попадают пустые значения или если контекст вычисления ограничен текущей группировкой.

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

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

Этот метод является наиболее универсальным и гибким, так как он позволяет имитировать работу оконных функций. Основная идея заключается в том, чтобы собрать все даты, в которых были продажи, в массив на уровне детальных записей, а затем выбрать из этого массива минимальное значение.

Проанализируем выражение, которое позволяет добиться нужного результата:


МИНИМУМ(ВычислитьВыражениеСГруппировкойМассив("ВЫБОР КОГДА Сумма(Количество) > 0 ТОГДА День ИНАЧЕ &ДатаОкончания КОНЕЦ", "Склад, Номенклатура, День"))

Разберем по шагам, что происходит в этой формуле:

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

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

Способ 2: Функция ВычислитьВыражение с контекстом «ДетальныеЗаписи»

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

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

ВычислитьВыражение("Минимум(Период)", , "ДетальныеЗаписи")

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

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

Способ 3: Оптимальное решение на уровне запроса

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

Мы можем создать временную таблицу, в которой заранее вычислим минимальную дату продажи для каждой пары товар-склад:


ВЫБРАТЬ
    Продажи.Склад КАК Склад,
    Продажи.Номенклатура КАК Номенклатура,
    МИНИМУМ(Продажи.Период) КАК ДатаПервойПродажи
ПОМЕСТИТЬ ВТ_ПервыеПродажи
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода
ГРУППИРОВАТЬ ПО
    Продажи.Склад,
    Продажи.Номенклатура

Затем мы просто соединяем эту таблицу с основной выборкой. В СКД поле ДатаПервойПродажи станет обычным ресурсом. Выясним преимущества этого метода:

Настройка ресурсов и обработка «дырок» в данных

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

Также важно правильно обрабатывать пустые значения (NULL). Если за весь период продаж по товару не было, функция Минимум может вернуть пустое значение. Чтобы отчет выглядел профессионально, разберем использование функции ЕстьNull:

ЕстьNull(Минимум(ДатаПродажи), &ДатаКонцаПериода)

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

Подведем итог: если вам нужно быстрое решение для небольшого отчета, используйте ВычислитьВыражениеСГруппировкойМассив. Если же вы проектируете сложный высоконагруженный отчет, лучше вычислить дату первой продажи заранее в тексте запроса через временные таблицы.

← На главную