Как рассчитать количество затрат на единицу продукции в запросе 1С

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При формировании производственной отчетности в конфигурациях на платформе 1С:Предприятие (например, 1С:УПП 1.3 или 1С:Комплексная автоматизация) часто возникает задача сопоставить объемы выпуска и списанные материальные затраты, чтобы получить удельный расход на единицу выпущенной продукции. Попытка решить эту задачу с помощью простой конструкции ОБЪЕДИНИТЬ ВСЕ в одном запросе нередко приводит к тому, что в строках с конкретными материалами удельный расход оказывается равен нулю.

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

В чем заключается проблема объединения таблиц

Проанализируем типичный запрос, в котором данные из регистра накопления ВыпускПродукции объединяются с данными регистра ЗатратыНаВыпускПродукции:


ВЫБРАТЬ
    ВыпускПродукцииОбороты.Подразделение КАК Подразделение,
    ВыпускПродукцииОбороты.Продукция КАК Продукция,
    ВыпускПродукцииОбороты.Спецификация КАК Спецификация,
    ВыпускПродукцииОбороты.ДокументВыпуска КАК ДокументВыпуска,
    НЕОПРЕДЕЛЕНО КАК Затрата,
    ВыпускПродукцииОбороты.КоличествоОборот КАК КоличествоПродукции,
    0 КАК КоличествоЗатрат
ИЗ
    РегистрНакопления.ВыпускПродукции.Обороты(&ДатаНач, &ДатаКон, , ) КАК ВыпускПродукцииОбороты

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ЗатратыНаВыпускПродукцииОбороты.Подразделение,
    ЗатратыНаВыпускПродукцииОбороты.Продукция,
    ЗатратыНаВыпускПродукцииОбороты.Спецификация,
    ЗатратыНаВыпускПродукцииОбороты.ДокументВыпуска,
    ЗатратыНаВыпускПродукцииОбороты.Затрата,
    0,
    ЗатратыНаВыпускПродукцииОбороты.КоличествоОборот
ИЗ
    РегистрНакопления.ЗатратыНаВыпускПродукции.Обороты(&ДатаНач, &ДатаКон, , ) КАК ЗатратыНаВыпускПродукцииОбороты

Выясним причину некорректного поведения при последующей группировке. В первой части запроса поле Затрата не заполнено (содержит НЕОПРЕДЕЛЕНО или NULL), но присутствует КоличествоПродукции. Во второй части запроса поле Затрата заполнено конкретной номенклатурой материала, но КоличествоПродукции равно 0.

Когда мы выполняем группировку по полю Затрата, СУБД формирует отдельные строки для каждого материала. В строке с конкретным материалом агрегатная функция СУММА(КоличествоПродукции) всегда дает 0, так как данные о выпуске попали только в строку с пустой затратой. В результате выражение вида СУММА(КоличествоЗатрат) / СУММА(КоличествоПродукции) возвращает ноль для каждой детальной строки и рассчитывается только в общих итогах или группировках по продукции, где оба потока сворачиваются вместе.

Так как язык запросов 1С не поддерживает оконные функции, получить количество выпуска в детальной строке затраты через простое объединение невозможно. Для решения задачи требуется изменить архитектуру выборки.

Решение 1: Использование временных таблиц и левого соединения

Классический и наиболее надежный способ в чистом запросе — подготовить две независимые таблицы во временных таблицах и связать их с помощью конструкции ЛЕВОЕ СОЕДИНЕНИЕ.

Разберем по шагам создание пакета запросов:

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

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


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Затраты.Подразделение КАК Подразделение,
    Затраты.Продукция КАК Продукция,
    Затраты.Спецификация КАК Спецификация,
    Затраты.ДокументВыпуска КАК ДокументВыпуска,
    Затраты.Затрата КАК Затрата,
    Затраты.КоличествоОборот КАК КоличествоЗатрат,
    Затраты.СуммаОборот КАК СуммаЗатрат
ПОМЕСТИТЬ ВТ_Затраты
ИЗ
    РегистрНакопления.ЗатратыНаВыпускПродукции.Обороты(&ДатаНач, &ДатаКон, , ) КАК Затраты
ИНДЕКСИРОВАТЬ ПО
    Подразделение,
    Продукция,
    Спецификация,
    ДокументВыпуска
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЕСТЬNULL(ВТ_Выпуск.Подразделение, ВТ_Затраты.Подразделение) КАК Подразделение,
    ЕСТЬNULL(ВТ_Выпуск.Продукция, ВТ_Затраты.Продукция) КАК Продукция,
    ЕСТЬNULL(ВТ_Выпуск.Спецификация, ВТ_Затраты.Спецификация) КАК Спецификация,
    ЕСТЬNULL(ВТ_Выпуск.ДокументВыпуска, ВТ_Затраты.ДокументВыпуска) КАК ДокументВыпуска,
    ВТ_Затраты.Затрата КАК Затрата,
    ЕСТЬNULL(ВТ_Выпуск.КоличествоПродукции, 0) КАК КоличествоПродукции,
    ЕСТЬNULL(ВТ_Выпуск.СтоимостьПродукции, 0) КАК СтоимостьПродукции,
    ЕСТЬNULL(ВТ_Затраты.КоличествоЗатрат, 0) КАК КоличествоЗатрат,
    ЕСТЬNULL(ВТ_Затраты.СуммаЗатрат, 0) КАК СуммаЗатрат,
    ВЫБОР
        КОГДА ЕСТЬNULL(ВТ_Выпуск.КоличествоПродукции, 0) <> 0
            ТОГДА ЕСТЬNULL(ВТ_Затраты.КоличествоЗатрат, 0) / ВТ_Выпуск.КоличествоПродукции
        ИНАЧЕ 0
    КОНЕЦ КАК КоличествоНаЕдиницуПродукции
ИЗ
    ВТ_Выпуск КАК ВТ_Выпуск
        ПОЛНОЕ СОЕДИНЕНИЕ ВТ_Затраты КАК ВТ_Затраты
        ПО ВТ_Выпуск.Подразделение = ВТ_Затраты.Подразделение
            И ВТ_Выпуск.Продукция = ВТ_Затраты.Продукция
            И ВТ_Выпуск.Спецификация = ВТ_Затраты.Спецификация
            И ВТ_Выпуск.ДокументВыпуска = ВТ_Затраты.ДокументВыпуска

Использование конструкции ПОЛНОЕ СОЕДИНЕНИЕ защищает от потери строк, если по какой-то причине выпуск был отражен без списания затрат или затраты были списаны без выпуска готовой продукции.

Решение 2: Расчет удельного показателя в СКД

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

Рассмотрим подробнее порядок настройки СКД:

  1. Оставляем исходный запрос с объединением двух регистров. В выборке присутствуют поля КоличествоПродукции и КоличествоЗатрат.
  2. Переходим на вкладку Ресурсы.
  3. Для базовых полей задаем стандартное суммирование: Сумма(КоличествоПродукции) и Сумма(КоличествоЗатрат).
  4. Добавляем ресурс КоличествоНаЕдиницуПродукции. В выражении для детальных записей и группировок по затратам используем контекстную функцию языка выражений СКД:
    
    Выбор
        Когда ВычислитьВыражение("Сумма(КоличествоПродукции)", "Продукция") <> 0
            Тогда Сумма(КоличествоЗатрат) / ВычислитьВыражение("Сумма(КоличествоПродукции)", "Продукция")
        Иначе 0
    Конец
    

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

Рекомендации по учету специфики производственных регистров

При сопоставлении регистров выпуска и затрат на выпуск важно учитывать особенности ведения учета:

  1. Аналитика распределения: В типовых конфигурациях затраты могут распределяться с точностью до заказа на производство или номенклатурной группы. Если связь по спецификациям или документам выпуска не заполнена, сопоставление по этим полям приведет к дублированию или пустым результатам.
  2. Документы распределения: Фактическое списание затрат на выпуск фиксируется не только оперативными документами (Отчет производства за смену), но и регламентными операциями закрытия месяца (Распределение материалов на выпуск, Расчет себестоимости выпуска). Период запроса должен охватывать проведение регламентных процедур.
← На главную