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

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

При построении отчетов или обработке данных в 1С часто возникает задача: имея список документов или записей регистра с датами изменения цен, необходимо вычислить «интервалы жизни» каждой конкретной цены. Например, если цена на товар менялась 1-го, 6-го и 15-го числа, нам нужно получить диапазоны: с 1-го по 5-е, с 6-го по 14-е и с 15-го по 31-е число. Рассмотрим, как решить эту задачу максимально эффективно.

Метод 1: Группировка данных в запросе

Если данные в вашей исходной таблице (временной или постоянной) уже содержат даты начала действия цен, самый простой способ — это использование агрегатных функций МИНИМУМ() и МАКСИМУМ() по сгруппированным данным. Однако важно помнить: этот метод корректно работает только в том случае, если вы сгруппировали данные так, чтобы в одну группу попадали строго строки с одинаковой ценой, идущие подряд.

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


ВЫБРАТЬ
    Т.Номенклатура,
    Т.Цена,
    МИНИМУМ(Т.Период) КАК НачалоПериода,
    МАКСИМУМ(Т.Период) КАК КонецПериода
ИЗ
    ВТ_Цены КАК Т
СГРУППИРОВАТЬ ПО
    Т.Номенклатура,
    Т.Цена

Важное примечание: Этот метод вернет только «минимальную» и «максимальную» даты из исходного набора. Если одна и та же цена встречается для номенклатуры в разные периоды, разделенные другой ценой, обычная группировка объединит их в один интервал. Для более точного расчета необходимо использовать дополнительные алгоритмы.

Метод 2: Постобработка в модуле объекта (Таблицы Значений)

В случаях, когда данные сложны и требуют логики «соседних строк» (чтобы определить дату окончания текущей цены по дате начала следующей), оптимальным решением является выгрузка результата запроса в ТаблицаЗначений. Это позволяет избежать сверхсложных соединений внутри языка запросов, которые могут сильно замедлить систему при больших объемах данных.

Разберем алгоритм по шагам:

  1. Выполняем запрос к РегистрСведений.ЦеныНоменклатуры или Документ.ПоступлениеТоваровУслуг, сортируя результат по Номенклатура и Период.
  2. Выгружаем полученный результат в таблицу значений методом Выгрузить().
  3. Обходим таблицу в цикле:
    • Если ТекущаяСтрока.Номенклатура совпадает с ПредыдущаяСтрока.Номенклатура, то мы устанавливаем ПредыдущаяСтрока.ДатаОкончания = ТекущаяСтрока.ДатаНачала - 1.
    • Если номенклатура изменилась, значит, закончился интервал для предыдущего товара.

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

Метод 3: Использование вспомогательного набора данных

Если вам необходимо оставаться строго в рамках запроса, можно реализовать подход с «искусственным» расширением интервалов. Вы можете получить таблицу всех дат изменений цен, а затем через ЛЕВОЕ СОЕДИНЕНИЕ сопоставить каждую дату с «ближайшей следующей датой» для той же номенклатуры.

Порядок действий:

  1. Создаем временную таблицу ВТ_ДатыЦен, содержащую только Номенклатура, Цена и Период.
  2. Соединяем таблицу саму с собой по условию Т1.Номенклатура = Т2.Номенклатура И Т2.Период > Т1.Период.
  3. Вычисляем КонецПериода как МИНИМУМ(Т2.Период) минус 1 секунда.

Такой метод позволяет получить четкие интервалы без необходимости выгрузки в ТаблицаЗначений, но требует осторожности при работе с очень большими выборками, так как соединение таблицы самой с собой может существенно нагрузить базу данных.

Заключение

Для решения задачи определения периодов цен мы рекомендуем комбинированный подход: используйте Запрос для получения «сырых» данных о датах и ценах, а для финальной подготовки отчетных интервалов — обработку в ТаблицаЗначений. Это обеспечит высокую производительность и позволит легко отлаживать логику формирования интервалов.

← На главную