В практике разработки на платформе 1С:Предприятие часто возникает задача объединения данных из двух разных источников (таблиц или временных наборов), которые имеют общие ключевые измерения. Типичная ситуация: у нас есть Таблица 1 с колонками А, Б, В и Таблица 2 с колонками А, Б, Г. Наша цель — получить результат в виде единой строки А, Б, В, Г, где поля А и Б выступают идентификаторами, а В и Г дополняют друг друга.
Простое использование оператора ОБЪЕДИНИТЬ ВСЕ без дополнительных манипуляций приведет к тому, что в итоговой выборке мы увидим две строки: в одной будет заполнено поле В (с пустым Г), а в другой — поле Г (с пустым В). Давайте разберем по шагам, как решить эту задачу максимально эффективно, используя механизмы запросов и Системы компоновки данных (СКД).
Это самый популярный и надежный способ, который работает практически в любой ситуации. Суть метода заключается в предварительном объединении всех записей в одну временную таблицу с последующей группировкой по ключевым полям.
Проанализируем алгоритм реализации:
А, Б, В. Для отсутствующего поля Г мы явно прописываем NULL (или значение по умолчанию).ОБЪЕДИНИТЬ ВСЕ.А, Б, а для поля В прописываем NULL, выбирая реальное значение только для Г.СГРУППИРОВАТЬ ПО ключевым полям А и Б, а к полям В и Г применяем агрегатную функцию МАКСИМУМ.Рассмотрим пример кода запроса:
ВЫБРАТЬ
Т1.А КАК ПолеА,
Т1.Б КАК ПолеБ,
Т1.В КАК ПолеВ,
NULL КАК ПолеГ
ПОМЕСТИТЬ ВТ_Данные
ИЗ
&Таблица1 КАК Т1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Т2.А,
Т2.Б,
NULL,
Т2.Г
ИЗ
&Таблица2 КАК Т2;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ.ПолеА,
ВТ.ПолеБ,
МАКСИМУМ(ВТ.ПолеВ) КАК ПолеВ,
МАКСИМУМ(ВТ.ПолеГ) КАК ПолеГ
ИЗ
ВТ_Данные КАК ВТ
СГРУППИРОВАТЬ ПО
ВТ.ПолеА,
ВТ.ПолеБ
Почему это работает? Функция МАКСИМУМ игнорирует значения NULL. Если для пары А и Б у нас есть одно значение в одной строке и NULL в другой, функция вернет именно значащую информацию, «схлопывая» две строки в одну.
Если данных не слишком много, можно воспользоваться конструкцией ПОЛНОЕ СОЕДИНЕНИЕ. Это позволяет избежать создания временных таблиц и сделать запрос более компактным. Основная сложность здесь заключается в корректной обработке ключевых полей, которые могут присутствовать как в первой, так и во второй таблице.
Выясним причину использования функции ЕСТЬNULL: так как при полном соединении записи могут отсутствовать в одной из сторон, нам нужно гарантировать, что ключевое поле в результате будет заполнено.
ВЫБРАТЬ
ЕСТЬNULL(Т1.А, Т2.А) КАК ПолеА,
ЕСТЬNULL(Т1.Б, Т2.Б) КАК ПолеБ,
Т1.В КАК ПолеВ,
Т2.Г КАК ПолеГ
ИЗ
&Таблица1 КАК Т1
ПОЛНОЕ СОЕДИНЕНИЕ &Таблица2 КАК Т2
ПО Т1.А = Т2.А
И Т1.Б = Т2.Б
Данный подход удобен, если вы уверены, что для каждой пары ключей в каждой таблице существует строго не более одной записи. Если же записей несколько, вы получите «картезианское произведение» (дублирование строк).
Бывают сложные случаи, когда для одного набора ключей А и Б в таблицах содержится несколько разных значений В и Г. Например, в Таблице 1 есть две строки (В1, В2), и в Таблице 2 есть две строки (Г1, Г2). Обычная группировка или соединение могут выдать некорректный результат.
Разберем, как реализовать механизм «номера по порядку» внутри запроса:
А и Б.Т1.Ссылка >= Т2.Ссылка (или по другому уникальному полю) с последующим подсчетом количества.А и Б, но и по этому служебному номеру.В результате мы получим сопоставление: первая строка из первой таблицы соединится с первой строкой из второй, вторая — со второй и так далее. Это позволяет выводить данные параллельно в две колонки, сохраняя структуру строк.
Если задача стоит в рамках разработки отчета, то СКД предоставляет встроенные инструменты для решения этой проблемы без написания сложных запросов. Рассмотрим этот вариант подробнее.
Посмотрим на настройки наборов данных:
А и Б.Также в СКД существует мощная функция СоединитьСтроки(). Если для одного ключа А и Б у вас много значений в колонке В, вы можете не плодить строки, а вывести их в одну ячейку через запятую. Это делается в поле «Выражение» на вкладке «Ресурсы»:
СоединитьСтроки(ВычислитьВыражениеТаблицаЗначений("В"), ", ")
При использовании любого из вышеперечисленных методов стоит помнить о производительности:
А и Б. Это критически важно для скорости выполнения операции СГРУППИРОВАТЬ ПО или СОЕДИНЕНИЕ на больших объемах данных.МАКСИМУМ универсальна. Она работает не только с числами, но и с датами и строками. Помните, что для строк МАКСИМУМ вернет то значение, которое стоит последним по алфавиту.ЕСТЬNULL(Поле, 0) или ЕСТЬNULL(Поле, "") поможет избежать пустых значений в интерфейсе пользователя.Проанализировав ситуацию, мы видим, что наиболее гибким и универсальным является первый метод с использованием ОБЪЕДИНИТЬ ВСЕ и временной таблицы. Он легко читается, просто отлаживается и работает предсказуемо даже при наличии пустых значений в исходных данных.