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

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

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

Разбор исходной проблемы

Рассмотрим ситуацию, когда у нас есть документ «Меню» с перечнем блюд, и нам нужно получить итоговый список продуктов для закупки или списания. Изначально автор темы пытался использовать сложную цепочку временных таблиц:


ВЫБРАТЬ * ПОМЕСТИТЬ ВР_Меню ИЗ &Таб КАК Таб;

ВЫБРАТЬ
    БлюдаИнгридиенты.Продукт КАК Продукт,
    БлюдаИнгридиенты.Количество КАК Количество,
    БлюдаИнгридиенты.СИ КАК СИ
ПОМЕСТИТЬ ВР_Продукты
ИЗ Справочник.Блюда.Ингридиенты КАК БлюдаИнгридиенты
ГДЕ БлюдаИнгридиенты.Ссылка В (ВЫБРАТЬ Блюдо ИЗ ВР_Меню);

ВЫБРАТЬ Продукт, СИ, СУММА(Количество)
ИЗ ВР_Продукты
СГРУППИРОВАТЬ ПО Продукт, СИ

На первый взгляд запрос кажется логичным, но он содержит ряд подводных камней. Проанализируем, почему такая конструкция может работать некорректно. Во-первых, использование ВЫБРАТЬ * при помещении во временную таблицу — это антипаттерн. Это не только избыточно нагружает память, но и может привести к ошибкам типизации, если колонки в исходной таблице значений &Таб не были жестко типизированы перед передачей в запрос.

Выясняем причину: почему группировка не работает?

Если запрос «не суммирует», это обычно означает одно из двух: либо поля, по которым идет группировка, на самом деле различаются, либо логика соединений приводит к дублированию или потере записей. Рассмотрим подробнее основные причины:

  1. Разные единицы измерения (СИ): Если в справочнике для одного продукта указаны разные единицы (например, «г» и «кг»), 1С воспримет их как разные значения для группировки. Даже если названия одинаковые, ссылки на элементы справочника могут быть разными.
  2. Проблема типов данных: Если поле Количество в таблице &Таб попало в запрос с типом «Произвольный», СУБД может некорректно выполнять агрегатные функции.
  3. Отсутствие связи с количеством порций: В исходном запросе автора полностью игнорируется количество самих блюд из меню. Суммируются просто строки из рецептур, как будто каждого блюда заказано по одной порции.

Оптимальное решение задачи

Для того чтобы запрос работал корректно и учитывал реальное количество блюд из меню, необходимо использовать ЛЕВОЕ СОЕДИНЕНИЕ (или ВНУТРЕННЕЕ СОЕДИНЕНИЕ) между списком блюд и табличной частью их состава. Проанализируем исправленный вариант запроса:


ВЫБРАТЬ
    ВР_Меню.Блюдо КАК БлюдоСсылка,
    ВР_Меню.КоличествоБлюд КАК КоличествоПорций
ПОМЕСТИТЬ ВР_Меню
ИЗ &Таб КАК ВР_Меню;

ВЫБРАТЬ
    Ингредиенты.Продукт КАК Продукт,
    Ингредиенты.СИ КАК СИ,
    СУММА(Ингредиенты.Количество * ВР_Меню.КоличествоПорций) КАК ОбщееКоличество
ИЗ
    ВР_Меню КАК ВР_Меню
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Блюда.Ингредиенты КАК Ингредиенты
    ПО ВР_Меню.БлюдоСсылка = Ингредиенты.Ссылка
СГРУППИРОВАТЬ ПО
    Ингредиенты.Продукт,
    Ингредиенты.СИ

В этом варианте мы решаем сразу несколько проблем. Во-первых, мы явно умножаем количество ингредиента в одной порции на количество порций из меню (Ингредиенты.Количество * ВР_Меню.КоличествоПорций). Во-вторых, мы избавляемся от лишних промежуточных временных таблиц, что ускоряет выполнение запроса.

Важные нюансы при работе с рецептурами

Рассмотрим дополнительные аспекты, которые часто встречаются в реальных задачах автоматизации общепита и которые необходимо учитывать профессиональному разработчику:

1. Учет коэффициентов единиц измерения. Чтобы избежать ситуации, когда картофель посчитан отдельно в «кг» и «г», рекомендуется приводить все показатели к базовой единице измерения продукта. В запросе это реализуется через соединение со справочником единиц измерения и умножение количества на Коэффициент.

2. Рекурсивный состав (Вложенные блюда). Если ваше «Блюдо 1» (например, сложный салат) содержит в составе «Полуфабрикат 1» (например, соус), то простой запрос к табличной части Ингредиенты не увидит состав соуса. Для решения таких задач в 1С применяется либо цикл в коде с последовательным разворачиванием ингредиентов во временные таблицы, либо построение дерева значений.

3. Брутто и Нетто. Обратите внимание, какое именно поле вы выбираете из справочника. Для целей складского учета и закупа продуктов всегда нужно использовать вес Брутто (вес продукта до очистки и термической обработки), иначе при приготовлении блюд у вас возникнет фактическая недостача на складе.

Итоги и рекомендации

Подведем итог нашему разбору. Если ваш запрос в 1С не суммирует данные:

  1. Проверьте, одинаковые ли ссылки в полях, по которым идет группировка (особенно в поле СИ).
  2. Убедитесь, что вы используете агрегатную функцию СУММА и блок СГРУППИРОВАТЬ ПО для всех несуммируемых полей.
  3. Всегда типизируйте колонки таблицы значений, передаваемой в запрос в качестве параметра.
  4. Используйте ВНУТРЕННЕЕ СОЕДИНЕНИЕ, если вам нужны только те продукты, по которым заполнена рецептура, чтобы исключить пустые строки в результате.

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

← На главную