При работе с Системой компоновки данных (СКД) разработчики часто сталкиваются с особенностью механизма Связи наборов данных. По умолчанию СКД выполняет соединение между источником и приемником по принципу Left Join (левое внешнее соединение). Это означает, что если в наборе-источнике отсутствует какая-либо комбинация измерений (например, определенный склад или номенклатура), то данные из набора-приемника по этим измерениям просто не попадут в итоговый отчет. В этой статье мы подробно разберем, как обойти это ограничение и добиться эффекта Полного соединения (Full Join) в СКД.
Для начала проанализируем ситуацию. Когда мы настраиваем связь на вкладке Связи наборов данных, СКД генерирует запросы к базе данных последовательно. Сначала получается выборка из «Источника связи», а затем для каждой строки источника выполняется запрос к «Приемнику связи» с передачей параметров. Если в источнике нет записи, запрос к приемнику по этому ключу даже не инициируется. Именно поэтому мы получаем классическое левое соединение.
Рассмотрим основной и самый эффективный способ решения этой задачи, который рекомендуют опытные разработчики.
Вместо того чтобы связывать наборы данных (запросы) между собой через вкладку связей, мы воспользуемся механизмом объединения на уровне самой структуры наборов. Это позволит нам собрать данные из всех источников в единый поток, сохраняя при этом все записи из каждого набора.
Разберем по шагам:
Запрос1, Запрос2, Запрос3).Однако простое объединение может «смешать» данные разных отчетов, если они должны выводиться отдельно. Чтобы этого избежать, применим метод поля-дискриминатора.
Проанализируем ситуацию: нам нужно вывести три разных таблицы и общие итоги в четвертой. Чтобы СКД понимала, какая запись к какому «отчету» относится, добавим в каждый запрос текстовое поле.
Пример для Запрос1:
ВЫБРАТЬ
"Продажи" КАК ИмяОтчета,
Организация,
Склад,
СуммаПродажи КАК Сумма
ИЗ
РегистрНакопления.Продажи
Пример для Запрос2:
ВЫБРАТЬ
"Остатки" КАК ИмяОтчета,
Организация,
Склад,
СуммаОстаток КАК Сумма
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки
Теперь в настройках СКД мы можем сгруппировать данные по полю ИмяОтчета. Это позволит нам вывести информацию в виде отдельных таблиц в одном отчете, а общие ресурсы будут суммироваться корректно по всем наборам, так как они находятся в одном родительском объединении.
Рассмотрим проблему, когда пользователь устанавливает отбор по полю, которое присутствует только в одном из наборов (например, ВидОплаты). Если мы просто наложим отбор на весь отчет, то записи из наборов, где этого поля нет, примут значение NULL и будут отсечены фильтром. В итоге отчет может выйти пустым.
Чтобы избежать этой проблемы, выполним следующие действия:
Запрос2 нет поля ВидОплаты, добавим его принудительно:
ВЫБРАТЬ
...,
ЗНАЧЕНИЕ(Справочник.ВидыОплаты.ПустаяСсылка) КАК ВидОплаты
ИЗ
...
Если по каким-то причинам использование «Набора данных — объединение» невозможно (например, сложная иерархия связей), можно применить метод Master Dataset. Мы создаем вспомогательный набор данных, который будет содержать все уникальные комбинации ключей из всех таблиц.
Рассмотрим структуру такого запроса:
ВЫБРАТЬ РАЗЛИЧНЫЕ Организация, Склад, Номенклатура ИЗ (
ВЫБРАТЬ Организация, Склад, Номенклатура ИЗ Регистр1
ОБЪЕДИНИТЬ
ВЫБРАТЬ Организация, Склад, Номенклатура ИЗ Регистр2
ОБЪЕДИНИТЬ
ВЫБРАТЬ Организация, Склад, Номенклатура ИЗ Регистр3
) КАК ВсеКлючи
Затем в окне связей мы назначаем этот набор Источником, а все остальные — Приемниками. Поскольку в источнике теперь гарантированно есть все возможные комбинации измерений, левое соединение от него ко всем остальным наборам фактически превращается в полное соединение.
Выясним, как считать общие итоги, если данные все же остались в разных наборах. В СКД существует мощный инструмент — функция ВычислитьВыражение. Она позволяет обращаться к данным других группировок или даже других наборов данных.
Например, чтобы получить сумму из другого набора в контексте текущей группировки, можно использовать конструкцию:
Сумма(ВычислитьВыражение("Сумма", , , "Первая", "Последняя", "НазваниеВторогоНабора"))
Это бывает полезно для вывода сравнительных показателей в одной строке, когда прямое объединение запросов затруднено из-за разной детальности данных.
Проанализируем нагрузку на систему. Использование связей наборов данных в СКД — это всегда серия запросов к СУБД. Если данных много (десятки тысяч строк в источнике), отчет может работать медленно. Набор данных — объединение обычно работает быстрее, так как компоновщик оптимизирует построение итогового запроса.
Подведем итог: Для имитации полного соединения в СКД наиболее правильным и современным подходом является использование Набора данных - объединение с предварительным «выравниванием» состава полей во всех вложенных запросах. Это гарантирует сохранение всех данных, корректную работу агрегатных функций (Сумма, Количество) и предсказуемое поведение пользовательских отборов.