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