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