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