При разработке отчетов в системе компоновки данных (СКД) часто возникает задача: сформировать список клиентов, приобретавших определенные группы или виды номенклатуры, и вывести их актуальные контактные данные (например, номера телефонов). Однако при прямом соединении документов продаж и контактной информации строки отчета начинают задваиваться. Разберем причины возникновения дублей и рассмотрим правильные варианты построения схемы компоновки данных.
Выясним причину появления повторяющихся данных в отчете. Задвоение строк возникает по двум основным факторам:
РеализацияТоваровУслуг.Товары возвращает столько строк, сколько раз клиент встретился в табличной части.КонтактнаяИнформация (или одноименном регистре сведений) у каждого партнера хранится множество записей: юридический адрес, фактический адрес, несколько телефонов, email. Если не наложить жесткий фильтр на вид и тип контактной информации, при левом соединении одна строка клиента размножится на количество всех его контактов.Рассмотрим классический вариант построения запроса в схеме компоновки данных. Для исключения дублирования разделим выборку на два логических шага: сначала получим уникальный список партнеров во временную таблицу, а затем присоединим к ним контактные данные строго определенного типа и вида.
Посмотрим на пример текста запроса для набора данных СКД:
ВЫБРАТЬ РАЗЛИЧНЫЕ
РеализацияТоваровУслуг.Партнер КАК Партнер
ПОМЕСТИТЬ ВТ_Партнеры
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка
{ГДЕ
РеализацияТоваровУслугТовары.Номенклатура.ВидНоменклатуры.* КАК ВидНоменклатуры,
РеализацияТоваровУслуг.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания}
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Партнеры.Партнер КАК Партнер,
ПартнерыКонтактнаяИнформация.НомерТелефона КАК НомерТелефона
ИЗ
ВТ_Партнеры КАК ВТ_Партнеры
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
ПО ВТ_Партнеры.Партнер = ПартнерыКонтактнаяИнформация.Ссылка
И (ПартнерыКонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон))
И (ПартнерыКонтактнаяИнформация.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонПартнера))
Обратите внимание на важные условия в тексте запроса:
РАЗЛИЧНЫЕ в первом пакете гарантирует, что в таблицу ВТ_Партнеры попадут только уникальные ссылки на партнеров, независимо от количества накладных.{}, что позволяет системе компоновки динамически управлять условиями отбора по датам и виду номенклатуры.Тип и конкретный Вид, чтобы исключить попадание адресов и прочих контактов.В типовых конфигурациях (1С:ERP, Комплексная автоматизация, Управление торговлей) обращение напрямую к табличным частям документов не рекомендуется из соображений производительности. Проанализируем более быстрое и правильное решение с использованием виртуальных таблиц оборотов регистров накопления (например, ВыручкаИСебестоимостьПродаж.Обороты или Продажи.Обороты).
Виртуальная таблица оборотов изначально возвращает свернутые данные, что ускоряет выборку и избавляет от лишних внутренних соединений между шапкой и табличной частью документов.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ВыручкаИСебестоимостьПродажОбороты.Партнер КАК Партнер
ПОМЕСТИТЬ ВТ_Партнеры
ИЗ
РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(
&ПериодНачала,
&ПериодОкончания,
Авто,
{АналитикаУчетаНоменклатуры.Номенклатура.ВидНоменклатуры.* КАК ВидНоменклатуры}) КАК ВыручкаИСебестоимостьПродажОбороты
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Партнеры.Партнер КАК Партнер,
ПартнерыКонтактнаяИнформация.НомерТелефона КАК НомерТелефона
ИЗ
ВТ_Партнеры КАК ВТ_Партнеры
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
ПО ВТ_Партнеры.Партнер = ПартнерыКонтактнаяИнформация.Ссылка
И (ПартнерыКонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон))
И (ПартнерыКонтактнаяИнформация.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонПартнера))
Схему компоновки данных можно построить без объединения разнородных источников в один сложный запрос. Разберем по шагам, как настроить отчет через связанные наборы данных:
КонтактнаяИнформация с фильтрацией по типу Телефон.НаборДанных_Продажи, приемник НаборДанных_Контакты, условие связи по полю Партнер = Ссылка (или Объект).Такой подход обеспечивает независимость логики получения данных и делает структуру схемы компоновки более гибкой для дальнейшей модификации.
Если у контрагента зарегистрировано несколько телефонов с одним и тем же видом контактной информации, простое левое соединение неизбежно размножит строки отчета. Рассмотрим два способа решения этой проблемы:
НомерТелефона формулу:
СоединитьСтроки(Массив(НомерТелефона), ", ")
Это позволит вывести все телефоны клиента в одной ячейке через запятую без создания дополнительных строк в группировке отчета.МАКСИМУМ:
ВЫБРАТЬ
ВТ_Партнеры.Партнер КАК Партнер,
МАКСИМУМ(ПартнерыКонтактнаяИнформация.НомерТелефона) КАК НомерТелефона
ИЗ
ВТ_Партнеры КАК ВТ_Партнеры
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
ПО ВТ_Партнеры.Партнер = ПартнерыКонтактнаяИнформация.Ссылка
И (ПартнерыКонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон))
И (ПартнерыКонтактнаяИнформация.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонПартнера))
СГРУППИРОВАТЬ ПО
ВТ_Партнеры.Партнер
Проанализируем технические ограничения, о которых необходимо помнить при написании запросов:
Представление, АдресЭП) могут иметь неограниченную длину. Использование операторов РАЗЛИЧНЫЕ или СГРУППИРОВАТЬ ПО к таким полям вызовет ошибку СУБД. Для обхода ограничения всегда приводите строковые поля к фиксированной длине: ВЫРАЗИТЬ(ПартнерыКонтактнаяИнформация.Представление КАК Строка(250)).Партнеры/Контрагенты, так и в независимом регистре сведений КонтактнаяИнформация. Если табличная часть пуста, замените источник данных на соответствующий регистр сведений.