При разработке запросов в системе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью объединения данных из «шапки» документа и его табличной части. На первый взгляд, существует несколько синтаксически верных способов решить эту задачу, которые кажутся идентичными. Однако при детальном анализе выясняется, что они по-разному нагружают сервер СУБД и возвращают разные наборы данных. В этой статье мы подробно разберем три основных варианта написания таких запросов, проанализируем их производительность и выясним, какой из них лучше использовать в различных ситуациях.
Рассмотрим первый вариант, который часто используется из-за своей лаконичности. В этом случае основной таблицей запроса выступает табличная часть документа, а данные шапки выбираются через обращение к полю Ссылка.
ВЫБРАТЬ
ЗаказТовары.Номенклатура КАК Номенклатура,
ЗаказТовары.Сумма КАК Сумма,
ЗаказТовары.Ссылка.Организация КАК Организация,
ЗаказТовары.Ссылка.Контрагент КАК Контрагент
ИЗ
Документ.Заказ.Товары КАК ЗаказТовары
Анализ логики: Этот запрос обладает важной особенностью — он вернет данные только по тем документам, у которых заполнена табличная часть Товары. Если документ Заказ существует, но в нем нет ни одной строки в товарах, он вообще не попадет в итоговую выборку. Это происходит потому, что «ведущей» здесь является именно таблица состава.
Производительность: С точки зрения SQL, современные версии платформы «1С» (начиная с 8.2) оптимизируют такие обращения. Несмотря на то, что в коде мы дважды обращаемся через «точку» (к организации и контрагенту), платформа создаст в SQL-запросе только одно левое соединение с основной таблицей документа. Это делает данный вариант достаточно производительным и легким для чтения.
Второй вариант предполагает использование классического SQL-подхода с явным соединением двух таблиц. Здесь основной таблицей выступает «шапка» документа.
ВЫБРАТЬ
Заказ.Организация КАК Организация,
Заказ.Контрагент КАК Контрагент,
ЗаказТовары.Номенклатура КАК Номенклатура,
ЗаказТовары.Сумма КАК Сумма
ИЗ
Документ.Заказ КАК Заказ
ЛЕВОЕ СОЕДИНЕНИЕ
Документ.Заказ.Товары КАК ЗаказТовары
ПО
ЗаказТовары.Ссылка = Заказ.Ссылка
Анализ логики: Проанализируем ситуацию с пустыми табличными частями. В отличие от первого варианта, ЛЕВОЕ СОЕДИНЕНИЕ гарантирует, что в результат попадут все документы Заказ, подходящие под условия фильтрации. Если у заказа нет товаров, в полях Номенклатура и Сумма мы получим значение NULL, но сама запись о документе (организация и контрагент) сохранится.
Производительность: Этот метод считается стандартом де-факто для сложных отчетов. Он дает разработчику полный контроль над типом соединения (Левое, Внутреннее, Полное). Однако стоит учитывать, что если нам нужны данные только по заполненным ТЧ, этот вариант может работать чуть медленнее первого из-за большего количества сканируемых записей в основной таблице (как показано в обсуждении на форуме, разница в количестве RecordsScanned может быть существенной).
Третий вариант является специфичным для платформы «1С». Он часто генерируется конструктором печати и позволяет получить иерархическую структуру прямо в результате запроса.
ВЫБРАТЬ
Заказ.Организация КАК Организация,
Заказ.Контрагент КАК Контрагент,
Заказ.Товары.(
Номенклатура КАК Номенклатура,
Сумма КАК Сумма
) КАК ЗаказТовары
ИЗ
Документ.Заказ КАК Заказ
Анализ логики: Выясним, почему этот вариант так популярен в печатных формах. При обходе результата такого запроса методом Выбрать(), мы получаем объект ВыборкаИзРезультатаЗапроса, внутри которого поле ЗаказТовары само является выборкой. Это позволяет писать изящный код обхода «цикл в цикле» без ручной проверки смены ссылки документа.
Скрытые механизмы и риски: Рассмотрим, что происходит «под капотом». Платформа транслирует этот запрос в SQL через создание временных таблиц (как видно из трассировки профайлера в сообщении №2). Сначала данные шапок помещаются во временную таблицу #tt2, а затем к ней присоединяются данные ТЧ.
tempdb.ОБЪЕДИНИТЬ ВСЕ).Проанализируем критически важный аспект, который не всегда очевиден при разработке под полными правами. Если в конфигурации настроены ограничения доступа на уровне записей (RLS):
Выясним, какой же вариант в итоге предпочтительнее. Ответ зависит от конкретной задачи:
ЛЕВЫМ СОЕДИНЕНИЕМ.Таким образом, хотя конструктор 1С часто предлагает вариант с вложенными таблицами, опытному разработчику следует отдавать предпочтение плоским запросам с явными или неявными соединениями для обеспечения максимальной производительности и предсказуемости результата.