Почему в отчете СКД не отображается номенклатура с нулевым остатком и как это исправить

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

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

Разберем причину: как СКД оптимизирует запросы

Первое, что нам необходимо понять — это механизм динамического формирования SQL-запросов в СКД. Система компоновки данных не просто выполняет тот текст запроса, который вы написали в схеме. Она анализирует выбранные пользователем поля, отборы и группировки, а затем «на лету» пересобирает запрос к базе данных, выбрасывая из него все, что считает лишним.

Когда мы используем виртуальную таблицу РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты, платформа 1С ведет себя следующим образом:

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

Проблема заключается в том, что в физических таблицах итогов 1С (особенно в таких конфигурациях, как УТ 11, ERP или КА) записи с нулевыми значениями часто просто не хранятся. Если ресурс закрылся в ноль, платформа может удалить соответствующую запись для экономии места и ускорения работы. В результате, обращаясь только к остаткам, мы не получаем записи о номенклатуре, по которой нет фактического остатка на складе.

Решение №1: Использование справочника как основного источника

Наиболее правильным и архитектурно верным способом решения данной задачи является использование справочника Номенклатура в качестве «мастер-таблицы». Это гарантирует, что в выборку попадут все нужные нам позиции, независимо от наличия движений в регистре.

Рассмотрим по шагам, как построить такой запрос:

  1. Создадим временную таблицу со списком всей необходимой номенклатуры (можно наложить фильтры по иерархии или свойствам).
  2. Левым соединением присоединим к этой таблице данные из виртуальной таблицы ОстаткиИОбороты.
  3. Обязательно обработаем возможные значения NULL с помощью функции ЕСТЬNULL.

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


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

В этом случае, даже если в таблице остатков нет записи для конкретной позиции, Справочник.Номенклатура вернет строку, а функция ЕСТЬNULL превратит пустоту в аккуратный ноль.

Решение №2: Настройка ролей полей в СКД

Иногда даже при правильном запросе СКД может продолжать скрывать строки. Это связано с тем, как настроены Роли на закладке «Наборы данных». Рассмотрим, на что стоит обратить внимание:

  1. Найдите поле, отвечающее за остаток (например, КонечныйОстаток).
  2. Убедитесь, что в колонке «Роль» указано, что это поле остатка, и правильно задано имя (например, Остаток).
  3. Проверьте связь с полем периода. Если вы используете периодичность (день, месяц), СКД должна понимать, к какому моменту времени относится этот ноль.

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

Решение №3: Обработка дополнения периодов

Если ваша задача — вывести остатки по дням, включая те дни, когда движений не было вовсе, вам поможет механизм Дополнения периодов в СКД. Разберем, как его настроить:

  1. Перейдите на закладку «Наборы данных».
  2. Для поля периода (например, ПериодДень) установите тип дополнения «День».
  3. Укажите начало и конец периода дополнения (обычно это параметры &НачалоПериода и &КонецПериода).

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

Выясним причину влияния цен

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

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

Подведем итоги

Для того чтобы ваш отчет всегда корректно отображал номенклатуру, даже если ее остаток равен нулю:

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

← На главную