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

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

При разработке отчетов и обработок в 1С часто возникает задача: сопоставить данные табличной части документа (например, ОприходованиеТоваров) с движениями по регистру накопления (например, ПродажиСебестоимость), чтобы увидеть, какими документами продажи была списана конкретная партия. Однако начинающие разработчики нередко сталкиваются с избыточными соединениями в тексте запроса и неожиданным задвоением строк. Разберем типичные ошибки и рассмотрим правильные варианты построения такого запроса.

Анализ типичных ошибок в запросе

Посмотрим на исходный вариант запроса, вызывающий проблемы:


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

В этом коде присутствуют две принципиальные проблемы:

  1. Избыточное соединение шапки и табличной части документа. Соединять таблицу Документ.ОприходованиеТоваров с ее же табличной частью Документ.ОприходованиеТоваров.Товары не требуется. Все реквизиты шапки документа доступны напрямую из табличной части через обращение к полю Ссылка (например, ОприходованиеТоваровТовары.Ссылка.Подразделение). Лишнее соединение усложняет запрос и снижает производительность СУБД.
  2. Задвоение строк из-за множественных движений. Один документ оприходования (партия) может списываться не одним документом продажи, а частями в нескольких реализациях. При левом соединении без группировки каждая строка табличной части оприходования продублируется столько раз, сколько раз данная номенклатура партии фигурирует в регистре ПродажиСебестоимость. Кроме того, если одна и та же номенклатура указана в табличной части документа в нескольких строках, произойдет перекрестное умножение строк.

Вариант 1. Оптимизация структуры запроса без лишних соединений

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


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

Такой запрос читается гораздо проще, однако при наличии нескольких продаж по одной партии строки всё равно будут множиться, а суммы оприходования — дублироваться в каждой строке.

Вариант 2. Использование временных таблиц и группировок

Для корректного сопоставления данных и предотвращения искажения числовых показателей разберем по шагам создание пакета запросов с временными таблицами:

  1. Свернем табличную часть документа по номенклатуре, чтобы исключить внутридокументные дубли, и просуммируем суммы.
  2. Получим из регистра уникальные комбинации партии, номенклатуры и регистратора продажи.
  3. Соединим подготовленные временные таблицы.

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


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ПродажиСебестоимость.ДокументОприходования КАК ДокументОприходования,
    ПродажиСебестоимость.Номенклатура КАК Номенклатура,
    ПродажиСебестоимость.Регистратор КАК ДокументПродажи
ПОМЕСТИТЬ ВТ_Продажи
ИЗ
    РегистрНакопления.ПродажиСебестоимость КАК ПродажиСебестоимость
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Оприходование.СтатьяЗатрат КАК СтатьяЗатрат,
    ВТ_Оприходование.Подразделение КАК Подразделение,
    ВТ_Оприходование.ДокументОприходования КАК ДокументОприходования,
    ВТ_Оприходование.Номенклатура КАК Номенклатура,
    ВТ_Оприходование.Сумма КАК Сумма,
    ВТ_Продажи.ДокументПродажи КАК ДокументПродажи
ИЗ
    ВТ_Оприходование КАК ВТ_Оприходование
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Продажи КАК ВТ_Продажи
        ПО ВТ_Оприходование.ДокументОприходования = ВТ_Продажи.ДокументОприходования
            И ВТ_Оприходование.Номенклатура = ВТ_Продажи.Номенклатура

Важные особенности учета себестоимости

При работе с партионным учетом и регистром ПродажиСебестоимость проанализируем следующие нюансы:

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