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