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

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

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

Разберем подробно причины этой ошибки и рассмотрим правильные варианты построения запроса в платформе «1С:Предприятие».

В чем заключается ошибка при использовании периодичности «Регистратор»

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


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

Выясним причину некорректной работы такого подхода:

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

Основное решение: отключение детальной периодичности

Для получения итоговых данных за период в разрезе аналитики достаточно оставить третий параметр (периодичность) виртуальной таблицы пустым. В этом случае платформа автоматически рассчитает ровно один начальный остаток на &НачалоПериода, сумму всех оборотов и один конечный остаток на &КонецПериода для каждой комбинации субконто.

Посмотрим на правильный текст запроса:


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

В данном запросе секция СГРУППИРОВАТЬ ПО отсутствует полностью, так как таблица сразу возвращает одну свернутую строку на каждую номенклатуру.

Важные практические рекомендации при работе с регистрами бухгалтерии

Разберем по шагам ключевые нюансы, влияющие на точность расчета и быстродействие запросов:

  1. Отказ от левых соединений для получения простых реквизитов: Если соединять таблицу остатков со справочником подчиненных единиц измерения (как это часто делают через ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмерения ПО ... = ЕдиницыИзмерения.Владелец), при наличии нескольких записей в справочнике произойдет размножение строк. Безопаснее обращаться к реквизиту напрямую через точку: ХозрасчетныйОстаткиИОбороты.Субконто1.БазоваяЕдиницаИзмерения.
  2. Использование параметра «ВидыСубконто»: В плане счетов на разных субсчетах счета 10 порядок аналитик может отличаться (на одном субсчете Субконто1 — Номенклатура, на другом — Склады). Чтобы зафиксировать строгую привязку, передадим в шестой параметр виртуальной таблицы массив нужных видов субконто:
    
    МассивСубконто = Новый Массив;
    МассивСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура);
    МассивСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады);
    Запрос.УстановитьПараметр("ВидыСубконто", МассивСубконто);
    
    В результате Субконто1 в запросе гарантированно будет Номенклатурой, а Субконто2 — Складом.
  3. Фильтрация внутри параметров виртуальной таблицы: Условия по счетам и субконто всегда следует задавать в круглых скобках виртуальной таблицы, а не в блоке ГДЕ. Это позволяет СУБД отфильтровать записи на этапе чтения итогов, что существенно ускоряет выполнение запроса.
  4. Проверка признаков счета: Если у счета или субконто включен признак «Только обороты» (оборотное субконто), поля начального и конечного остатков всегда будут возвращать NULL или 0. Убедимся, что аналитика является остаточной.
  5. Границы расчетного периода: Чтобы учесть все движения последнего дня выбранного интервала, параметр &КонецПериода необходимо передавать с точностью до конца суток (КонецДня(КонецПериода)) либо использовать объект Граница с параметром ВидГраницы.ВключаяГраницу.

Альтернатива: реализация через Систему компоновки данных (СКД)

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

← На главную