Как правильно соединить справочник Номенклатура с регистром Продажи в 1С, чтобы вывести всю номенклатуру?

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

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

Причина возникновения ошибки

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

Если в блоке ГДЕ мы пишем условие вида ГДЕ ПродажиОбороты.Контрагент = &Контрагент, то для всех товаров, у которых не было продаж, поле Контрагент будет равно NULL. Условие сравнения с конкретным контрагентом отсекает эти NULL-значения, и наше «левое» соединение фактически превращается во «внутреннее». То есть остаются только те позиции, где продажа была.

Решение 1: Фильтрация в параметрах виртуальной таблицы

Самый правильный и производительный способ решения задачи — перенести условие фильтрации непосредственно в параметры виртуальной таблицы Обороты. В этом случае 1С сначала выполнит выборку из регистра только по нужному контрагенту, а уже потом присоединит результат к справочнику. Благодаря этому записи без продаж останутся в выборке.

Рассмотрим пример правильного запроса:


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

Решение 2: Использование функции ЕСТЬNULL

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

Пример синтаксиса: ЕСТЬNULL(ПродажиОбороты.КоличествоОборот, 0). Это гарантирует, что даже если продаж не было, в колонке будет стоять число 0, а не пустое значение.

Полезные советы по оптимизации запроса

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

Применяя эти простые правила, вы сможете легко формировать любые отчеты по продажам, включая те, где требуется видеть товары с «нулевыми» показателями. Попробуйте переписать ваш запрос, перенеся условие из ГДЕ в параметры таблицы Обороты, и вы увидите, что результат сразу станет корректным.

← На главную