При разработке отчетов и обработок в платформе 1С:Предприятие разработчики часто сталкиваются с необходимостью сопоставить и сгруппировать данные из двух источников (например, двух таблиц значений, документов или регистров). В таких случаях возникает дилемма: использовать ПОЛНОЕ СОЕДИНЕНИЕ с обработкой отсутствующих значений через функцию ЕСТЬNULL или применить конструкцию ОБЪЕДИНИТЬ ВСЕ с последующей группировкой. Разберем по шагам особенности каждого подхода, их влияние на производительность и рекомендации стандартов разработки 1С.
Рассмотрим, как работает исходная конструкция. При выполнении полного соединения двух таблиц строки, присутствующие только в первом источнике, дополняются значениями NULL для полей второго источника, и наоборот. Чтобы получить единый непустой идентификатор (например, номенклатуру или характеристику), применяется функция ЕСТЬNULL(Поле1, Поле2), которая возвращает значение второго поля, если первое равно NULL.
Пример такого запроса:
ВЫБРАТЬ
ЕСТЬNULL(Т1.Номенклатура, Т2.Номенклатура) КАК Номенклатура,
ЕСТЬNULL(Т1.Характеристика, Т2.Характеристика) КАК Характеристика,
ЕСТЬNULL(Т1.Количество, 0) КАК Количество1,
ЕСТЬNULL(Т2.Количество, 0) КАК Количество2
ИЗ
Таблица1 КАК Т1
ПОЛНОЕ СОЕДИНЕНИЕ Таблица2 КАК Т2
ПО Т1.Номенклатура = Т2.Номенклатура
И Т1.Характеристика = Т2.Характеристика
Проанализируем скрытые проблемы и подводные камни этой конструкции:
NULL = NULL дает результат UNKNOWN (ложь). Если в каком-либо из полей сопоставления (например, характеристика не заполнена и имеет значение NULL) окажется NULL в обоих источниках, строки не соединятся между собой, а продублируются в результирующей выборке как две отдельные записи.ЕСТЬNULL обрабатывает исключительно системный тип NULL. Если поля в источниках имеют несовместимые типы данных, результирующая колонка может получить составной тип, что усложнит дальнейшую обработку и выгрузку в таблицу значений. Кроме того, ЕСТЬNULL не заменяет пустые ссылки, пустые строки и нулевые даты.ПОЛНОЕ СОЕДИНЕНИЕ оптимизаторы СУБД (особенно PostgreSQL, а также MS SQL Server) не могут эффективно применить технику проброса предикатов (Predicate Pushdown) и использовать быстрые индексные соединения (Index Nested Loops). СУБД вынуждена выполнять тяжелые операции Hash Join или Merge Join, что при больших объемах данных приводит к повышенной нагрузке на память и сбросу промежуточных результатов на диск (в tempdb или временные файлы).Стандарты разработки 1С рекомендуют избегать использования полного соединения при сведении и агрегации таблиц. Вместо этого оптимальным паттерном является вертикальное объединение наборов данных через ОБЪЕДИНИТЬ ВСЕ с последующей группировкой.
Разберем по шагам правильный алгоритм построения такого запроса:
0).ОБЪЕДИНИТЬ ВСЕ выбираем измерения второй таблицы, нулевые значения для ресурсов первой таблицы и фактические значения ресурсов второй таблицы.СГРУППИРОВАТЬ ПО со сверткой числовых ресурсов через агрегатную функцию СУММА().Посмотрим на практический пример реализации:
ВЫБРАТЬ
ВложенныйЗапрос.Номенклатура КАК Номенклатура,
ВложенныйЗапрос.Характеристика КАК Характеристика,
СУММА(ВложенныйЗапрос.Количество1) КАК Количество1,
СУММА(ВложенныйЗапрос.Количество2) КАК Количество2
ИЗ
(ВЫБРАТЬ
Т1.Номенклатура КАК Номенклатура,
Т1.Характеристика КАК Характеристика,
Т1.Количество КАК Количество1,
0 КАК Количество2
ИЗ
Таблица1 КАК Т1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Т2.Номенклатура КАК Номенклатура,
Т2.Характеристика КАК Характеристика,
0 КАК Количество1,
Т2.Количество КАК Количество2
ИЗ
Таблица2 КАК Т2) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Номенклатура,
ВложенныйЗапрос.Характеристика
Выясним, почему данный подход считается более надежным и производительным:
ОБЪЕДИНИТЬ ВСЕ выполняется СУБД в потоковом режиме без накладных расходов на проверку уникальности строк, после чего последующая группировка по полям отрабатывает значительно быстрее и предсказуемее тяжелого полного соединения.NULL корректно сворачиваются в одну итоговую запись, исключая дублирование данных.ЕСТЬNULL для каждого измерения, что делает текст запроса более читаемым и снижает вероятность логических ошибок.Итог: хотя синтаксис ПОЛНОЕ СОЕДИНЕНИЕ с функцией ЕСТЬNULL является синтаксически допустимым в платформе 1С, для задач сопоставления и сведения данных из двух таблиц следует использовать конструкцию ОБЪЕДИНИТЬ ВСЕ с группировкой.