При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда итоговые данные начинают "множиться". Обычный отчет по заказам превращается в полотно с повторяющимися строками номенклатуры или дублирующимися суммами. Разберем подробно, почему это происходит и как правильно спроектировать запрос, чтобы отчет работал корректно.
Основная причина появления лишних строк — это так называемое Декартово произведение (Cartesian Product). В контексте 1С это чаще всего происходит при попытке соединить в одном запросе две таблицы типа "много" к одной таблице типа "один".
Проанализируем типичную ситуацию. У нас есть основной документ ЗаказКлиента. К нему мы присоединяем:
Если мы выполняем ВНУТРЕННЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ только по полю Ссылка заказа, система для каждой строки товара выведет столько строк, сколько найдено реализаций. В итоге вместо 10 строк мы получим 50 (10 товаров * 5 реализаций). Если к этому добавить регистр сведений с историей статусов, количество строк может вырасти в геометрической прогрессии.
В современных конфигурациях (ERP 2, УТ 11, КА 2) для связи строк заказа и реализации недостаточно использовать только ссылку на документ. Рассмотрим пример правильного соединения. В табличных частях "Товары" обоих документов существует поле КлючСвязи. Это уникальный идентификатор строки, который позволяет сопоставить конкретный товар в заказе с конкретным товаром в отгрузке.
Посмотрим на пример запроса с использованием ключей связи:
ВЫБРАТЬ
тбЗаказТовары.Номенклатура,
тбЗаказТовары.Количество КАК Заказано,
тбРеализацияТовары.Количество КАК Отгружено
ИЗ
Документ.ЗаказКлиента.Товары КАК тбЗаказТовары
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК тбРеализацияТовары
ПО тбЗаказТовары.Ссылка = тбРеализацияТовары.ЗаказКлиента
И тбЗаказТовары.КлючСвязи = тбРеализацияТовары.КлючСвязи
Если в вашей конфигурации нет поля КлючСвязи, необходимо выполнять соединение по Номенклатуре и Характеристике. Однако помните, что если одна и та же номенклатура встречается в заказе дважды разными строками, без уникального ключа дубли все равно могут возникнуть.
Это самый профессиональный и надежный способ решения проблемы дублей в 1С. Вместо того чтобы писать один огромный запрос со множеством соединений, мы создаем несколько независимых Наборов данных - запрос на закладке "Наборы данных".
Рассмотрим по шагам, как это реализовать:
СостоянияЗаказовКлиентов.После этого переходим на закладку "Связи наборов данных". Здесь мы указываем, что НаборДанных1 является источником, а остальные — приемниками. Связь настраиваем по полю ЗаказКлиента. СКД сама выполнит левое соединение в памяти, корректно сгруппирует данные и не допустит размножения строк товаров из-за нескольких документов отгрузки.
Часто дубли возникают из-за того, что в выборку попадают помеченные на удаление или непроведенные документы. В условии связи или в блоке ГДЕ обязательно нужно проверять состояние документов.
Проанализируем фрагмент кода с проверкой статуса:
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК докРеализация
ПО докРеализация.ЗаказКлиента = докЗаказКлиента.Ссылка
И докРеализация.Проведен = ИСТИНА
И докРеализация.ПометкаУдаления = ЛОЖЬ
Если дублируются абсолютно идентичные строки (например, вы не выводите номер реализации, но соединение с ней создало лишние записи), можно использовать ключевое слово РАЗЛИЧНЫЕ. Но используйте его с осторожностью: на больших объемах данных это существенно замедляет выполнение запроса, так как СУБД приходится выполнять дополнительную сортировку для поиска уникальных записей.
Если структура запроса неизбежно порождает дубли на уровне записей, мы можем "объяснить" системе компоновки, как их обрабатывать. На закладке "Наборы данных" в колонке "Роли" для поля ЗаказКлиента (или другого ключевого поля) можно настроить параметры:
СУММА(ВЫЧИСЛИТЬВЫРАЖЕНИЕОБЩИЕИТОГИ("МАКСИМУМ(Сумма)", "Заказ")) в ресурсах, чтобы сумма по заказу не складывалась пять раз при наличии пяти отгрузок.Если вы не можете понять, какая именно таблица "двоит" данные, рекомендуем использовать метод последовательного подключения таблиц:
Документ.ЗаказКлиента.Товары. Проверьте результат.Документ.ЗаказКлиента (шапка). Обычно здесь проблем не возникает.РегистрСведений.СостоянияЗаказовКлиентов. Если количество строк увеличилось — проблема в нем (значит, для одного заказа там больше одной записи).Такой пошаговый анализ позволит быстро локализовать "проблемную" таблицу и применить к ней группировку или выбрать МАКСИМУМ значений, чтобы гарантировать уникальность записей.