Как вывести номенклатуру с нулевым остатком в запросе 1С: использование ЕСТЬNULL и левого соединения

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

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

Почему функция ЕСТЬNULL не помогает в обычном запросе?

Разберем типичную ситуацию. Программист пишет запрос напрямую к виртуальной таблице остатков:


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

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

Решение проблемы: использование ЛЕВОГО СОЕДИНЕНИЯ

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

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

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

Главная ловушка: условие ГДЕ превращает левое соединение во внутреннее

Выясним причину, по которой решение с левым соединением часто не срабатывает у новичков. Если мы наложим условие по номенклатуре в секции ГДЕ, используя поле из правой таблицы (таблицы остатков), запрос снова станет пустым.

Важный момент: когда СУБД выполняет ЛЕВОЕ СОЕДИНЕНИЕ, для отсутствующих товаров в полях регистра проставляется NULL. Если в секции ГДЕ стоит фильтр типа ОстаткиТоваров.Номенклатура = &ТекНом, система отсечет все строки с NULL, так как NULL не может быть равен ссылке. Таким образом, левое соединение фактически превращается во внутреннее.

Чтобы этого избежать, мы должны накладывать условие либо на левую таблицу (Справочник), либо (что еще лучше) внутри параметров виртуальной таблицы остатков.

Оптимизация через параметры виртуальных таблиц

Для повышения производительности, особенно на больших базах данных, крайне рекомендуется передавать фильтры напрямую в параметры виртуальной таблицы. Проанализируем, как это работает: платформа 1С сначала отфильтровывает записи в регистре, подготавливая маленькую выборку, и только потом соединяет её со справочником. Это значительно быстрее, чем соединять весь справочник со всеми остатками и только потом фильтровать результат.


// Правильное использование параметров:
РегистрНакопления.СвободныеОстатки.Остатки(&КонецПериода, Номенклатура = &ТекНом)

Работа с характеристиками и сериями

Ситуация усложняется, если нам нужно получить остатки в разрезе характеристик или серий. Рассмотрим подробнее: если товара нет на остатке, то в регистре нет записи не только по номенклатуре, но и по конкретной связке «Номенклатура + Характеристика».

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

  1. Сначала выбрать все характеристики нужного товара из справочника ХарактеристикиНоменклатуры.
  2. Левым соединением добавить к ним остатки из регистра по этой связке.

Использование временных таблиц в сложных отчетах

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

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

Такой подход делает код чище, а выполнение запроса — предсказуемым для оптимизатора СУБД.

Особенности функции ЕСТЬNULL() и типов данных

Посмотрим на технические нюансы функции ЕСТЬNULL(Поле, ЗначениеЗамены). Важно помнить, что тип возвращаемого значения при замене NULL будет соответствовать типу второго аргумента.

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

Реализация на уровне программного кода

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


Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
    // Обработка ситуации: создаем строку вручную или выводим сообщение
КонецЕсли;

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

Резюме

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

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

← На главную