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