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