Почему в отчете СКД дублируются записи при соединении таблиц и как это исправить

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

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

Выясним причину: почему возникают дубли

Основная причина появления лишних строк — это так называемое Декартово произведение (Cartesian Product). В контексте 1С это чаще всего происходит при попытке соединить в одном запросе две таблицы типа "много" к одной таблице типа "один".

Проанализируем типичную ситуацию. У нас есть основной документ ЗаказКлиента. К нему мы присоединяем:

  1. Табличную часть Товары (в одном заказе может быть 10 товаров).
  2. Таблицу документов РеализацияТоваровУслуг (один заказ может отгружаться пятью разными реализациями).

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

Решение 1: Использование связи по ключу строки

В современных конфигурациях (ERP 2, УТ 11, КА 2) для связи строк заказа и реализации недостаточно использовать только ссылку на документ. Рассмотрим пример правильного соединения. В табличных частях "Товары" обоих документов существует поле КлючСвязи. Это уникальный идентификатор строки, который позволяет сопоставить конкретный товар в заказе с конкретным товаром в отгрузке.

Посмотрим на пример запроса с использованием ключей связи:


ВЫБРАТЬ
    тбЗаказТовары.Номенклатура,
    тбЗаказТовары.Количество КАК Заказано,
    тбРеализацияТовары.Количество КАК Отгружено
ИЗ
    Документ.ЗаказКлиента.Товары КАК тбЗаказТовары
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК тбРеализацияТовары
    ПО тбЗаказТовары.Ссылка = тбРеализацияТовары.ЗаказКлиента
    И тбЗаказТовары.КлючСвязи = тбРеализацияТовары.КлючСвязи

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

Решение 2: Разделение на несколько наборов данных в СКД

Это самый профессиональный и надежный способ решения проблемы дублей в 1С. Вместо того чтобы писать один огромный запрос со множеством соединений, мы создаем несколько независимых Наборов данных - запрос на закладке "Наборы данных".

Рассмотрим по шагам, как это реализовать:

  1. НаборДанных1: Выбираем данные по заказам и их товарам (основная таблица).
  2. НаборДанных2: Выбираем данные по реализациям (только ссылки, суммы и нужные реквизиты реализации).
  3. НаборДанных3: Выбираем данные из регистра СостоянияЗаказовКлиентов.

После этого переходим на закладку "Связи наборов данных". Здесь мы указываем, что НаборДанных1 является источником, а остальные — приемниками. Связь настраиваем по полю ЗаказКлиента. СКД сама выполнит левое соединение в памяти, корректно сгруппирует данные и не допустит размножения строк товаров из-за нескольких документов отгрузки.

Решение 3: Фильтрация по статусу документа и РАЗЛИЧНЫЕ

Часто дубли возникают из-за того, что в выборку попадают помеченные на удаление или непроведенные документы. В условии связи или в блоке ГДЕ обязательно нужно проверять состояние документов.

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


ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК докРеализация
ПО докРеализация.ЗаказКлиента = докЗаказКлиента.Ссылка
И докРеализация.Проведен = ИСТИНА
И докРеализация.ПометкаУдаления = ЛОЖЬ

Если дублируются абсолютно идентичные строки (например, вы не выводите номер реализации, но соединение с ней создало лишние записи), можно использовать ключевое слово РАЗЛИЧНЫЕ. Но используйте его с осторожностью: на больших объемах данных это существенно замедляет выполнение запроса, так как СУБД приходится выполнять дополнительную сортировку для поиска уникальных записей.

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

Если структура запроса неизбежно порождает дубли на уровне записей, мы можем "объяснить" системе компоновки, как их обрабатывать. На закладке "Наборы данных" в колонке "Роли" для поля ЗаказКлиента (или другого ключевого поля) можно настроить параметры:

Практические советы по диагностике

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

  1. Оставьте в запросе только выборку из Документ.ЗаказКлиента.Товары. Проверьте результат.
  2. Добавьте соединение с Документ.ЗаказКлиента (шапка). Обычно здесь проблем не возникает.
  3. Подключите РегистрСведений.СостоянияЗаказовКлиентов. Если количество строк увеличилось — проблема в нем (значит, для одного заказа там больше одной записи).
  4. Последним этапом подключайте таблицу реализаций.

Такой пошаговый анализ позволит быстро локализовать "проблемную" таблицу и применить к ней группировку или выбрать МАКСИМУМ значений, чтобы гарантировать уникальность записей.

← На главную