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

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

При решении задач анализа продаж, планирования закупок и расчета среднедневного расхода часто требуется определить, сколько дней за выбранный интервал товар фактически присутствовал на складе, а сколько дней отсутствовал (out-of-stock). Рассмотрим различные подходы к реализации такого расчета в запросе платформы 1С:Предприятие.

Особенности работы с виртуальными таблицами остатков

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

Для решения задачи применяются три основных подхода:

  1. Генерация непрерывного календаря дат и соединение с регистром остатков.
  2. Использование механизмов Системы компоновки данных (СКД) с автоматическим дополнением периода.
  3. Интервальный расчет по точкам изменения остатка (без поденной развертки).

Способ 1. Соединение таблицы дат с регистром остатков

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

Разберем по шагам построение такого запроса:

  1. Создаем временную таблицу дат периода. Ее можно получить из производственного календаря, регламентированного регистра сведений с датами либо сгенерировать программно и передать как параметр.
  2. Формируем список требуемой номенклатуры и выполняем декартово произведение списка товаров и календаря дат. В результате получаем полную матрицу «Товар — День».
  3. Присоединяем актуальный остаток на каждый день и агрегируем результат.

Посмотрим на пример формирования и расчета через временную таблицу дат:


ВЫБРАТЬ
    Календарь.Дата КАК Период,
    СписокНоменклатуры.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_ТоварыДни
ИЗ
    &ТаблицаКалендаря КАК Календарь
    ДРОБНОЕ ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ &ТаблицаНоменклатуры КАК СписокНоменклатуры
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Номенклатура КАК Номенклатура,
    ВТ.Период КАК Период,
    ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) КАК Остаток
ПОМЕСТИТЬ ВТ_ОстаткиПоДням
ИЗ
    ВТ_ТоварыДни КАК ВТ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
        ,
        Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ &ТаблицаНоменклатуры)
    ) КАК ТоварыНаСкладахОстатки
    ПО ВТ.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОстаткиПоДням.Номенклатура КАК Номенклатура,
    СУММА(ВЫБОР
        КОГДА ВТ_ОстаткиПоДням.Остаток > 0 ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоДнейСНаличиемОстаткаНаСкладе,
    СУММА(ВЫБОР
        КОГДА ВТ_ОстаткиПоДням.Остаток <= 0 ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоДнейБезОстаткаНаСкладе
ИЗ
    ВТ_ОстаткиПоДням КАК ВТ_ОстаткиПоДням
СГРУППИРОВАТЬ ПО
    ВТ_ОстаткиПоДням.Номенклатура

Важное замечание по производительности: Декартово соединение большого массива товаров с длинным периодом (например, 10 000 товаров × 365 дней = 3,65 млн строк) создает высокую нагрузку на СУБД и tempdb. Данный метод подходит для небольших списков позиций или коротких интервалов.

Способ 2. Использование возможностей дополнения периодов в СКД

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

Разберем по шагам настройку схемы компоновки данных:

  1. В запросе набора данных обращаемся к виртуальной таблице ОстаткиИОбороты регистра накопления с периодичностью ДЕНЬ.
  2. На вкладке «Наборы данных» для поля ПериодДень указываем роль «Период» и устанавливаем тип дополнения «День», указав параметры начала и окончания периода.
  3. В вычисляемых полях или ресурсах настраиваем агрегацию с условием наличия остатка: Сумма(Выбор Когда ВНаличииКонечныйОстаток > 0 Тогда 1 Иначе 0 Конец)
  4. В настройках структуры отчета выводим группировку по номенклатуре с итоговыми полями по дням.

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

Проанализируем наиболее производительный вариант для чистого SQL-запроса на больших объемах данных. Вместо создания строки на каждый день вычисляются интервалы между смежными датами смены остатка.

  1. Выбираем только те даты, когда остаток переходил через ноль (появлялся на складе или списывался полностью).
  2. С помощью функции РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, ДЕНЬ) рассчитываем длину интервала, на протяжении которого остаток сохранял положительное или нулевое значение.
  3. Суммируем полученные интервалы по каждой позиции номенклатуры. Такой подход работает в разы быстрее, так как оперирует только реальными изменениями состояния регистра.

Учет методических и прикладных нюансов

При расчете дней наличия товара важно учитывать логику предметной области и типовых конфигураций (например, 1С:Управление торговлей или 1С:ERP):

  1. Учет резервов и доступного остатка: Физическое присутствие товара на складе (регистр ТоварыНаСкладах) не всегда означает возможность его продажи или закупки. Если весь остаток зарезервирован под заказы клиентов, свободный остаток равен нулю. Для корректного расчета закупки следует использовать регистры доступных остатков (например, ЗапасыИПотребности) по формуле ВНаличии - ВРезерве.
  2. Внутридневные движения: Если товар поступил утром и был полностью отгружен в тот же день, остаток на начало и на конец дня будет равен 0. Чтобы не потерять факт наличия товара в этот день, в условии следует проверять не только конечный остаток, но и приход/расход:
    
    ВЫБОР
        КОГДА НачальныйОстаток + Приход > 0 ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ
    
  3. Отрицательные остатки: Если в конфигурации отключен контроль отрицательных остатков, регистр может содержать значения меньше нуля. Условие наличия всегда должно быть строго Количество > 0, а не Количество <> 0.
  4. Рабочие дни склада: При планировании закупок дни отсутствия товара часто сопоставляют с графиком работы склада. Если склад не работал в выходные, отсутствие отгрузок не является признаком дефицита.
← На главную