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