При разработке отчетов, обработок и бизнес-логики в платформе 1С часто возникает задача отобрать только те документы, у которых заполнена конкретная табличная часть. Например, требуется получить список документов ПоступлениеТоваровУслуг, в которых присутствуют строки в табличной части Оборудование. Рассмотрим подробно несколько вариантов построения таких запросов, разберем их плюсы и особенности выполнения на уровне базы данных SQL.
Если из документа требуется получить только саму ссылку или реквизиты, доступные через ссылку, самым простым и производительным решением является прямой запрос к таблице табличной части объекта. Поскольку одна табличная часть может содержать множество строк для одного и того же документа, необходимо исключить дублирование ссылок с помощью ключевого слова РАЗЛИЧНЫЕ или сгруппировав результат по полю Ссылка.
Рассмотрим пример запроса с получением уникальных ссылок документов:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ПоступлениеТоваровУслуг.Ссылка КАК Ссылка
ИЗ
Документ.ПоступлениеТоваровУслуг.Оборудование КАК ПоступлениеТоваровУслуг
Аналогичного результата можно добиться с помощью группировки. Разберем пример с условием по дате и организации:
ВЫБРАТЬ
ПоступлениеТоваровУслугОборудование.Ссылка КАК Ссылка
ИЗ
Документ.ПоступлениеТоваровУслуг.Оборудование КАК ПоступлениеТоваровУслугОборудование
ГДЕ
ПоступлениеТоваровУслугОборудование.Ссылка.Организация = &Организация
И ПоступлениеТоваровУслугОборудование.Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон
СГРУППИРОВАТЬ ПО
ПоступлениеТоваровУслугОборудование.Ссылка
Этот способ удобен тем, что в источнике ИЗ используется только таблица табличной части. Документы, у которых табличная часть пуста, в эту таблицу вообще не попадают, что автоматически отсекает лишние записи.
Если основным источником запроса выступает таблица шапки документа (например, когда нужно выбирать множество реквизитов шапки или накладывать на них сложные условия), применяется соединение таблиц. Чтобы отсечь документы без строк в табличной части, необходимо использовать внутреннее соединение (ВНУТРЕННЕЕ СОЕДИНЕНИЕ).
Частая ошибка — использование ЛЕВОЕ СОЕДИНЕНИЕ с последующей проверкой Ссылка ЕСТЬ НЕ NULL или ограничением по первой строке. Это усложняет текст запроса и снижает его читаемость. Правильным подходом является использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ с ограничением на первую строку табличной части (НомерСтроки = 1), чтобы избежать размножения записей шапки.
Разберем готовый пример такого запроса:
ВЫБРАТЬ
ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
ПоступлениеТоваровУслуг.Организация КАК Организация,
ПоступлениеТоваровУслуг.ВидОперации КАК ВидОперации
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Оборудование КАК ПоступлениеТоваровУслугОборудование
ПО ПоступлениеТоваровУслуг.Ссылка = ПоступлениеТоваровУслугОборудование.Ссылка
И ПоступлениеТоваровУслугОборудование.НомерСтроки = 1
ГДЕ
ПоступлениеТоваровУслуг.Организация = &Организация
И ПоступлениеТоваровУслуг.ВидОперации = &ВидОперации
Благодаря условию НомерСтроки = 1 внутренняя связь сработает ровно один раз для каждого документа, у которого есть хотя бы одна строка в табличной части, и исключит необходимость делать тяжелую операцию СГРУППИРОВАТЬ ПО или РАЗЛИЧНЫЕ.
Еще один распространенный и читаемый вариант — использование вложенного запроса в секции ГДЕ Ссылка В (...). Этот подход позволяет отбирать реквизиты из шапки документа без риска получить дубли строк из-за табличной части.
Рассмотрим структуру данного запроса:
ВЫБРАТЬ
ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
ПоступлениеТоваровУслуг.Организация КАК Организация
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
ГДЕ
ПоступлениеТоваровУслуг.Организация = &Организация
И ПоступлениеТоваровУслуг.Ссылка В
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ТЧ.Ссылка
ИЗ
Документ.ПоступлениеТоваровУслуг.Оборудование КАК ТЧ)
Проанализируем техническую сторону выполнения таких запросов на уровне СУБД (Microsoft SQL Server). Когда в языке запросов 1С используется обращение через точку от реквизита типа «Ссылка» (например, ПоступлениеТоваровУслугОборудование.Ссылка.Организация), платформа скрыто от разработчика формирует соединение с таблицей шапки документа.
Реквизит Ссылка в таблице табличной части содержит только уникальный идентификатор (GUID). Чтобы узнать организацию или дату документа, платформе требуется сопоставить этот GUID с первичным ключом физической таблицы шапки.
Посмотрим на результат трансляции запроса к табличной части с условием по реквизиту шапки в реальный SQL-код:
exec sp_executesql N'SELECT T1._Document173_IDRRef
FROM _Document173_VT4267 T1 WITH(NOLOCK)
LEFT OUTER JOIN _Document173 T2 WITH(NOLOCK) ON T1._Document173_IDRRef = T2._IDRRef
WHERE (T2._Fld4202RRef = @P1)
GROUP BY T1._Document173_IDRRef',N'@P1 varbinary(16)',0x0000...
Как видим, платформа 1С автоматически подставляет LEFT OUTER JOIN (левое внешнее соединение) с таблицей шапки _Document173. Если же разработчик явно прописывает ВНУТРЕННЕЕ СОЕДИНЕНИЕ в запросе 1С, оптимизатор СУБД получает прямой указатель на использование INNER JOIN.
Важные выводы по производительности:
(Ссылка, НомерСтроки), поэтому отборы по полю Ссылка с условием НомерСтроки = 1 выполняются максимально быстро.ЕстьОборудование), заполняемый при записи объекта.Иногда при выполнении запросов к табличным частям разработчики сталкиваются с ситуацией, когда запрос возвращает пустой результат, хотя в форме документа данные отображаются. Выясним причину на реальном примере из конфигураций 1С:ЗУП / 1С:ERP.
В некоторых обновлениях типовых конфигураций архитектура хранения данных меняется. Например, в документе СведенияОСтраховомСтажеЗастрахованныхЛицСЗВ_СТАЖ табличная часть ЗаписиОСтаже при проведении документа может очищаться, а сами данные переносятся в регистр сведений (в данном случае — ЗаписиСтраховогоСтажа).
Поэтому если запрос к табличной части проводимого документа не возвращает строк, необходимо проверить: