Почему отчет в 1С показывает завышенные или удвоенные значения и как это исправить?

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

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

Причина 1: Проблема «Картезианского произведения» при соединении таблиц

Основная причина завышения данных — это ситуация, когда одной строке из таблицы остатков соответствует несколько строк из таблицы цен (или другого справочника/регистра). Рассмотрим ситуацию на примере регистра ТоварыНаСкладах и регистра сведений ЦеныНоменклатуры. Если мы просто соединяем остатки с ценами по полю Номенклатура, а в регистре цен на одну позицию задано несколько значений (например, на разные даты или по разным характеристикам), система «размножит» строку с остатком для каждой найденной цены.

Проанализируем фрагмент некорректного кода, который часто приводит к таким последствиям:


ВЫБРАТЬ
    Таб.КоличествоНачальныйОстаток,
    Таб.КоличествоПриход,
    МАКСИМУМ(БазоваяЦена.Цена) КАК Цена
ИЗ
    Таб КАК Таб
ВНУТРЕННЕЕ СОЕДИНЕНИЕ БазоваяЦена КАК БазоваяЦена
    ПО Таб.Номенклатура = БазоваяЦена.Номенклатура
СГРУППИРОВАТЬ ПО
    Таб.КоличествоНачальныйОстаток,
    Таб.КоличествоПриход

В этом примере группировка и получение максимума происходят уже ПОСЛЕ соединения. Если в таблице БазоваяЦена для одной номенклатуры есть три записи, то до выполнения группировки (СГРУППИРОВАТЬ ПО) запрос создаст три строки с одинаковым количеством. Если в ресурсах СКД стоит функция Сумма, то итоговый результат будет утроен. Чтобы этого избежать, необходимо сначала получить уникальную цену во временной таблице, а уже затем соединять её с остатками.

Причина 2: Неправильное использование виртуальной таблицы «Остатки и Обороты»

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

Рассмотрим важный нюанс: если товар лежал на складе 10 дней без движения, и мы выбрали периодичность День, запрос может выдать 10 строк. При попытке просуммировать КоличествоНачальныйОстаток в СКД мы получим десятикратное завышение.

Правило работы с остатками: Остатки нельзя просто суммировать. Начальный остаток должен браться на начало первого периода отчета, а конечный — на конец последнего. Для этого в Системе компоновки данных (СКД) необходимо правильно настраивать Роли полей. У полей остатка должна стоять роль «Остаток», указано имя и тип (Начальный/Конечный).

Шаг 1: Подготовка уникальных цен во временной таблице

Для того чтобы избежать дублирования строк при соединении, мы должны гарантировать, что для каждой номенклатуры (и характеристики, если ведется учет) в таблице цен будет только одна запись. Посмотрим, как это реализовать через временную таблицу:


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

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

Обратите внимание на использование ЛЕВОЕ СОЕДИНЕНИЕ. Если использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ, то товары, на которые не установлена цена, просто пропадут из отчета. Это часто является еще одной ошибкой, приводящей к неполным данным.

Шаг 2: Настройка ресурсов в СКД

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

Часто разработчики забывают добавить агрегатную функцию, из-за чего на детальных записях данные есть, а в итогах по группировкам или в общем итоге — пусто или нули.

Проанализируем ситуацию с расходом. Если расход считается неверно, проверьте следующие моменты:

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

Методика отладки: пошаговый контроль

Если отчет продолжает выдавать странные цифры, проанализируем ситуацию методом исключения, используя Консоль запросов:

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

Итог: Для получения корректных данных всегда разделяйте получение «базиса» (количества) и «дополнений» (цены, коэффициенты, реквизиты) через временные таблицы. Контролируйте уникальность ключей соединения и правильно настраивайте роли полей остатков в СКД. Это гарантирует точность ваших отчетов и отсутствие претензий со стороны пользователей.

← На главную