Как вывести товары с нулевым итоговым оборотом в виртуальной таблице «Хозрасчетный.Обороты»?

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

При разработке отчетов в системе «1С:Предприятие» программисты часто сталкиваются с неочевидным поведением виртуальных таблиц оборотов. Типичная ситуация: за выбранный период по определенному товару были движения, например, приход на сумму +5 000 рублей и последующий возврат или сторно на сумму -5 000 рублей. Логически суммарный оборот за период равен нулю. Однако при попытке вывести этот товар в отчет с помощью виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.Обороты строка с этим товаром просто исчезает из результата запроса. Возникает резонный вопрос: как заставить систему вывести товар с итоговым нулевым оборотом?

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

Выясняем причину: почему СУБД «схлопывает» нулевые обороты?

Для того чтобы понять, почему строка с товаром пропадает, нам необходимо заглянуть «под капот» платформы 1С и посмотреть, как она взаимодействует с сервером баз данных (будь то MS SQL Server, PostgreSQL или другая СУБД). Виртуальные таблицы не существуют в базе данных физически — они формируются динамически в момент выполнения запроса.

Когда мы обращаемся к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Обороты с периодичностью Период (или вообще без указания периодичности), платформа транслирует наш запрос в SQL-запрос с группировкой по аналитике (субконто) и периодам. На стороне СУБД это выглядит как использование конструкции GROUP BY.

С целью оптимизации производительности, уменьшения сетевого трафика между сервером приложений 1С и СУБД, а также для исключения пустых строк платформа 1С автоматически накладывает условие фильтрации на сгруппированные данные. В SQL-запросе это реализуется с помощью конструкции HAVING. Платформа проверяет, чтобы хотя бы один из суммируемых числовых ресурсов (дебетовый оборот, кредитовый оборот или общий оборот) не был равен нулю. Если в результате сложения +5 и -5 по всем ресурсам получается чистый ноль, СУБД просто отбрасывает эту строку. Она физически не передается на сервер приложений 1С, и мы получаем пустой результат запроса.

Способ 1. Использование временной таблицы с периодичностью «Запись» (Рекомендуемый способ)

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

Рассмотрим этот алгоритм по шагам:

  1. Первый этап (выборка детальных записей): Мы обращаемся к виртуальной таблице оборотов, но устанавливаем параметр Периодичность в значение Запись (или Регистратор). В этом случае СУБД не будет группировать движения разных документов в одну строку, так как они относятся к разным записям регистра. Строки с положительными и отрицательными оборотами будут выбраны как отдельные записи и не схлопнутся. Полученный результат мы сохраняем во временную таблицу.
  2. Второй этап (группировка временной таблицы): Мы пишем второй запрос в пакете, в котором выбираем данные из нашей временной таблицы и самостоятельно группируем их с помощью конструкции СГРУППИРОВАТЬ ПО по нужной аналитике (например, по номенклатуре). На этом этапе СУБД честно сложит детальные строки, получит итоговый 0 и выведет строку, поскольку на временные таблицы пользователя автоматические условия HAVING платформы 1С не накладываются.

Давайте посмотрим на практический пример реализации этого способа в коде запроса:


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

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

Способ 2. Запрос к физической таблице движений (с контролем активности)

Если по каким-то причинам вы не хотите использовать временные таблицы, можно обратиться напрямую к таблице движений регистра бухгалтерии — РегистрБухгалтерии.Хозрасчетный. Однако этот способ требует от разработчика повышенного внимания к деталям и понимания структуры хранения данных.

При работе с физической таблицей движений необходимо учитывать два важнейших нюанса:

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

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


ВЫБРАТЬ
    ХозрасчетныйДвижения.СубконтоДт1 КАК Товар,
    СУММА(ВЫБОР
            КОГДА ХозрасчетныйДвижения.СчетДт = &СчетУчета
                ТОГДА ХозрасчетныйДвижения.Сумма
            ИНАЧЕ -ХозрасчетныйДвижения.Сумма
        КОНЕЦ) КАК СуммаОборот
ИЗ
    РегистрБухгалтерии.Хозрасчетный КАК ХозрасчетныйДвижения
ГДЕ
    ХозрасчетныйДвижения.Период МЕЖДУ &НачалоПериода И &КонецПериода
    И ХозрасчетныйДвижения.Активность = ИСТИНА
    И (ХозрасчетныйДвижения.СчетДт = &СчетУчета ИЛИ ХозрасчетныйДвижения.СчетКт = &СчетУчета)
СГРУППИРОВАТЬ ПО
    ХозрасчетныйДвижения.СубконтоДт1

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

Способ 3. Левое соединение со справочником (Вывод всего списка товаров)

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

Алгоритм реализации этого подхода:

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

Посмотрим на пример реализации левого соединения:


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

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

Особенности работы в Системе компоновки данных (СКД)

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

Для того чтобы избежать нежелательного поведения в СКД, рекомендуется:

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

← На главную