Как составить запрос по бухгалтерским счетам для получения сумм поступления и реализации товара без дублирования строк?

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

При разработке отчетов в программе «1С:Бухгалтерия 3.0» программисты часто сталкиваются с необходимостью сопоставить данные о закупках товаров (поступлениях) и их последующей продаже (реализации). На первый взгляд задача кажется простой: достаточно выгрузить обороты по счету 41 (Товары) в связке со счетом 60 (Поставщики) и обороты по счету 62 (Покупатели) в связке со счетом 90 (Продажи). Однако при объединении этих данных в один запрос начинающие разработчики часто сталкиваются с неприятным эффектом — дублированием строк, из-за чего итоговые суммы в отчете увеличиваются в несколько раз.

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

---

Анализ исходного запроса и поиск причин дублирования

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

  1. втВыручка — обороты между дебетом счета 62.01 и кредитом счета 90.01.1 для получения сумм продаж в разрезе товаров и документов реализации.
  2. втПриход — обороты между дебетом счета 41 и кредитом счета 60 для получения сумм поступлений в разрезе товаров и документов прихода.
  3. втНДС — обороты по счету учета НДС для выделения налога из сумм продаж.

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

Ошибка №1: Декартово произведение (Cross Join) с таблицей НДС

Обратим внимание на то, как в финальном запросе присоединяется таблица втНДС:


ИЗ
    втПриход КАК втПриход
    ЛЕВОЕ СОЕДИНЕНИЕ втВыручка КАК втВыручка
    ПО втПриход.ТоварПриход = втВыручка.Товар,
    втНДС КАК втНДС

Использование запятой перед таблицей втНДС без указания ключевого слова ПО и условий связи означает выполнение операции полного соединения (декартова произведения). В результате СУБД берет каждую строку, полученную от соединения таблиц прихода и расхода, и умножает ее на каждую строку из таблицы НДС. Если в таблице НДС содержится 100 записей, то количество строк в вашем отчете увеличится ровно в 100 раз! Это грубейшая синтаксическая ошибка.

Ошибка №2: Связь «многие-ко-многим» по полю Товар

Вторая, более глубокая архитектурная ошибка кроется в условии связи прихода и выручки:

ПО втПриход.ТоварПриход = втВыручка.Товар

В детальных таблицах втПриход и втВыручка записи хранятся в разрезе документов (регистраторов). Если за выбранный период определенный товар поступал на склад 5 раз (разными документами) и продавался 10 раз (разными документами), то при левом соединении только по полю товара система создаст связь «каждый с каждым». В итоге для этого товара мы получим 5 * 10 = 50 строк в отчете. Суммы прихода и расхода при этом будут многократно продублированы.

---

Вариант решения №1: Группировка данных (свертка по товарам)

Если перед вами стоит задача вывести сопоставление общих объемов закупок и продаж по товарам за период без детализации до конкретных документов, то лучшим решением будет предварительная группировка (агрегация) данных во временных таблицах.

Разберем этот подход по шагам. Мы должны полностью исключить детальные поля (такие как Регистратор, НомерСтроки, Дата) из временных таблиц и сгруппировать данные по номенклатуре.

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


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

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

// Шаг 3: Соединяем данные по товару (связь один-к-одному)
ВЫБРАТЬ
    втПриходГрупп.Товар КАК Товар,
    ЕСТЬNULL(втПриходГрупп.СуммаПоступления, 0) КАК СуммаПоступления,
    ЕСТЬNULL(втВыручкаГрупп.СуммаПродажи, 0) КАК СуммаПродажи
ИЗ
    втПриходГрупп КАК втПриходГрупп
    ЛЕВОЕ СОЕДИНЕНИЕ втВыручкаГрупп КАК втВыручкаГрупп
        ПО втПриходГрупп.Товар = втВыручкаГрупп.Товар

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

---

Вариант решения №2: Точное сопоставление через партионный учет

Что делать, если пользователю все-таки необходимо видеть детальный отчет с указанием конкретных документов закупки и продажи, при этом четко понимая, какое именно поступление было продано конкретной реализацией?

В типовой конфигурации «1С:Бухгалтерия 3.0» по умолчанию ведется партионный учет на счете 41. Это означает, что третьим субконто на счете 41 выступает документ партии (обычно это ДокументРасчетовСКонтрагентом или непосредственно документ поступления).

Когда мы проводим документ «Реализация товаров и услуг», система делает проводку списания себестоимости: Дебет 90.02.1 (Себестоимость продаж) – Кредит 41.01 (Товары на складах). В этой проводке:

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


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    вт.Товар КАК Товар,
    вт.ДокументПоступленияПартия КАК ДокументПоступления,
    вт.ДокументПродажи КАК ДокументРеализации,
    вт.КоличествоПродано КАК Количество,
    вт.СебестоимостьСписания КАК Себестоимость,
    // Получаем цену продажи из выручки (Дт 62 - Кт 90.01)
    ЕСТЬNULL(Выручка.СуммаОборот, 0) КАК СуммаПродажи,
    // Получаем сумму НДС по этой реализации
    ЕСТЬNULL(НДС.СуммаОборот, 0) КАК СуммаНДСПродажи
ИЗ
    втПродажиИПартии КАК вт
    
    // Присоединяем выручку по конкретному документу и товару
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, Авто, 
        ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Покупатели), , 
        ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Выручка), , ) КАК Выручка
    ПО вт.ДокументПродажи = Выручка.Регистратор
    И вт.Товар = Выручка.СубконтоКт2 // Аналитика Номенклатура на счете 90.01
    
    // Присоединяем НДС по документу продажи
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, Авто, 
        ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Продажи_НДС), , 
        ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Покупатели), , ) КАК НДС
    ПО вт.ДокументПродажи = НДС.Регистратор

Рассмотрим преимущества этого запроса:

  1. Мы берем за основу факт списания конкретной партии (проводка Дт 90.02 - Кт 41). В ней уже заложена связь между документом продажи (Регистратор) и документом закупки (СубконтоКт3).
  2. Мы присоединяем выручку и НДС строго по полям Регистратор и Товар. Связь получается однозначной, что полностью исключает дублирование строк.
  3. Этот отчет будет максимально информативен для конечного пользователя, так как покажет реальную картину рентабельности каждой сделки в разрезе закупленных партий.

---

Совет по использованию стандартных отчетов

Если перед вами стоит задача быстро сопоставить взаимосвязи между счетами и контрагентами без программирования, не забывайте о возможностях стандартных отчетов 1С. Отличным инструментом является отчет «Обороты между субконто».

Перейдите в раздел «Отчеты» — «Стандартные отчеты» — «Обороты между субконто». Настроив вид субконто как Номенклатура, а корр. субконто как Контрагенты или Договоры, вы получите готовую аналитическую таблицу движения активов, сформированную платформой автоматически.

← На главную