Как исправить неверный расчет количества и кратное завышение итогов в отчете СКД

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

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

Причина проблемы: эффект «размножения» строк

Основная причина расхождения цифр (например, когда вместо ожидаемых 15 000 мы получаем 170 000) — это классическое «раздувание» выборки при соединении таблиц в одном запросе. Рассмотрим ситуацию: вы соединяете таблицу остатков из регистра и таблицу оборотов из документов. Если в документах за выбранный период есть несколько записей по одной и той же номенклатуре и складу, то при соединении по этим полям каждая строка из таблицы остатков «размножится» на количество соответствующих строк из документов.

Проанализируем пример из практики: пользователь соединяет ТоварыОрганизаций.ОстаткиИОбороты и Документ.РеализацияТоваровУслуг.Товары. Если по одной номенклатуре было 10 реализаций, начальный остаток из регистра в итоговой таблице будет просуммирован 10 раз, что приведет к колоссальной ошибке в отчете.

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

В 1С считается «лучшей практикой» разделение таких запросов на разные Наборы данных. Вместо того чтобы писать один огромный запрос с ВНУТРЕННИМ СОЕДИНЕНИЕМ, мы создаем два независимых набора данных:

  1. НаборДанныхОстатки: Запрос к виртуальной таблице регистра накопления.
  2. НаборДанныхРеализации: Запрос к документам или оборотам для получения расхода.

После этого на закладке «Связи наборов данных» мы устанавливаем связь по полям Номенклатура, Склад и Организация. СКД в этом случае сначала получит итоги по каждому набору отдельно, а затем соединит их в памяти. Это полностью исключает дублирование ресурсов и гарантирует точность итогов.

Решение 2: Правильная параметризация через фигурные скобки

Чтобы отборы пользователя (например, по конкретному складу или организации) работали эффективно и не вызывали лишних данных в выборке, необходимо использовать синтаксис фигурных скобок {} в тексте запроса. Это позволяет СКД передавать условия напрямую в параметры виртуальных таблиц.

Рассмотрим, как должен выглядеть фрагмент запроса с использованием расширения языка запросов СКД:


ВЫБРАТЬ
    ТоварыОрганизацийОстаткиИОбороты.Организация КАК Организация,
    ТоварыОрганизацийОстаткиИОбороты.АналитикаУчетаНоменклатуры.СкладскаяТерритория КАК Склад,
    ТоварыОрганизацийОстаткиИОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ТоварыОрганизацийОстаткиИОбороты.КоличествоНачальныйОстаток КАК НачальныйОстаток
ИЗ
    РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(&Дата1, &Дата2, , , {Организация.*, АналитикаУчетаНоменклатуры.СкладскаяТерритория.* КАК Склад}) КАК ТоварыОрганизацийОстаткиИОбороты
ГДЕ
    {ТоварыОрганизацийОстаткиИОбороты.Организация.*, ТоварыОрганизацийОстаткиИОбороты.АналитикаУчетаНоменклатуры.СкладскаяТерритория.* КАК Склад}

Использование конструкции {Организация.*} внутри параметров виртуальной таблицы гарантирует, что СУБД отсечет лишние данные еще на этапе чтения из базы, а не после формирования всей таблицы остатков.

Решение 3: Проверка соединений с ценами и контрагентами

Выясним еще одну скрытую причину завышения данных — соединение с ценами через СрезПоследних. Если в регистре сведений ЦеныНоменклатуры цены хранятся в разрезе характеристик, а в соединении вы не указали поле Характеристика, запрос выдаст столько строк для одной номенклатуры, сколько цен для разных характеристик зафиксировано в базе.

Проанализируем правильный подход к соединению с ценами:

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

Решение 4: Настройка ролей полей в СКД

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

Разберем алгоритм настройки:

  1. Перейдите на закладку «Наборы данных».
  2. Для поля КоличествоНачальныйОстаток в колонке «Роль» нажмите на кнопку редактирования.
  3. Укажите тип «Остаток», выберите имя (например, Количество) и установите тип «Начальное».
  4. Укажите поле периода и соответствующие измерения (Склад, Номенклатура).

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

Рекомендация по архитектуре запроса

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

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

← На главную