Система компоновки данных (СКД) в 1С — это не просто построитель отчетов, а мощный генератор запросов, который на лету изменяет исходный текст запроса в зависимости от настроек пользователя. Одним из самых загадочных инструментов для начинающих (и не только) разработчиков являются расширения языка запросов, заключаемые в фигурные скобки {}. Особенно много вопросов вызывает их использование внутри вложенных запросов. Разберем детально, зачем это нужно и как это работает, в том числе когда используется пользовательская СКД. Для интерактивной настройки и построения отчетов на стороне клиентского приложения можно использовать инструмент «Пользовательская СКД».
Для начала вспомним, что фигурные скобки в СКД — это инструкции для процессора компоновки данных. Когда мы пишем обычный запрос, он статичен. Но как только мы добавляем расширения, задействуя процессор схемы запроса, мы говорим системе: «Если пользователь выбрал это поле, добавь его в реальный запрос к базе данных, а если не выбрал — удали». Рассмотрим основные секции расширений:
{ВЫБРАТЬ...} — управляет списком доступных и выбираемых полей.{ГДЕ...} — позволяет накладывать условия, которые будут применены только при заполнении соответствующих параметров или отборов (например, сравнение строки с представлением ссылки в запросе).{УПОРЯДОЧИТЬ ПО...} — определяет правила сортировки, доступные пользователю.{ХАРАКТЕРИСТИКИ...} — используется для работы с дополнительными реквизитами и сведениями.Теперь проанализируем ситуацию, когда эти конструкции встречаются внутри подзапроса или объединения (ОБЪЕДИНИТЬ ВСЕ). На первый взгляд кажется, что это дублирование, но это далеко не так.
Разберем конкретный пример из практики, когда в СКД снят флаг Автозаполнение. Это ситуация, когда разработчик берет на себя полную ответственность за описание полей компоновки. Если мы не укажем расширения во вложенном запросе, СКД может просто «не увидеть» поля, которые находятся внутри него, или не сможет эффективно пробросить туда отборы.
Основные причины использования {ВЫБРАТЬ...} внутри подзапроса:
СуммаОплаченоПоставщикам нужно только в одной части объединения и пользователь его не выбрал, расширение позволит системе «вырезать» лишнюю логику только из этой части.Рассмотрим фрагмент запроса, который вызвал вопросы. Обратим внимание на то, как структурированы вложенные поля:
ВЫБРАТЬ
ВложеныйЗапрос.ЗаказПокупателя КАК ЗаказПокупателя,
ВложеныйЗапрос.Номенклатура КАК Номенклатура,
СУММА(ВложеныйЗапрос.Количество) КАК Количество,
СУММА(ВложеныйЗапрос.Сумма) КАК Сумма,
СУММА(ВложеныйЗапрос.КоличествоОтгружено) КАК КоличествоОтгружено,
СУММА(ВложеныйЗапрос.СуммаОтгружено) КАК СуммаОтгружено,
СУММА(ВложеныйЗапрос.СуммаРасход) КАК СуммаРасход,
СУММА(ВложеныйЗапрос.СуммаОплаченоПоставщикам) КАК СуммаОплаченоПоставщикам
{ВЫБРАТЬ ЗаказПокупателя.*, Номенклатура.*, Количество, Сумма, КоличествоОтгружено, СуммаОтгружено, СуммаРасход, СуммаОплаченоПоставщикам}
ИЗ (
ВЫБРАТЬ
ВТ_Остатки.ЗаказПокупателя КАК ЗаказПокупателя,
ВТ_Остатки.Номенклатура КАК Номенклатура,
СУММА(ВТ_Остатки.Количество) КАК Количество,
СУММА(ВТ_Заказы.Цена * ВТ_Остатки.Количество) КАК Сумма,
0 КАК КоличествоОтгружено,
0 КАК СуммаОтгружено,
0 КАК СуммаРасход,
0 КАК СуммаОплаченоПоставщикам
{ВЫБРАТЬ ЗаказПокупателя.*, Номенклатура.*, Количество, Сумма, КоличествоОтгружено, СуммаОтгружено, СуммаРасход КАК СуммаРасход, СуммаОплаченоПоставщикам}
ИЗ ВТ_Остатки КАК ВТ_Остатки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Заказы КАК ВТ_Заказы ПО ВТ_Остатки.ЗаказПокупателя = ВТ_Заказы.ЗаказПокупателя И ВТ_Остатки.Номенклатура = ВТ_Заказы.Номенклатура
СГРУППИРОВАТЬ ПО ВТ_Остатки.ЗаказПокупателя, ВТ_Остатки.Номенклатура
) КАК ВложеныйЗапрос
{ГДЕ ВложеныйЗапрос.ЗаказПокупателя.*, ВложеныйЗапрос.Номенклатура.*}
СГРУППИРОВАТЬ ПО ВложеныйЗапрос.Номенклатура, ВложеныйЗапрос.ЗаказПокупателя
Проанализируем ситуацию: здесь мы видим использование {ВЫБРАТЬ ...} как во внешнем запросе, так и во вложенном. Рассмотрим подробнее, что дает конструкция ЗаказПокупателя.*. Символ «звездочка» после поля в фигурных скобках сообщает СКД, что пользователю должны быть доступны для выбора все дочерние реквизиты этого объекта. Если бы мы написали просто ЗаказПокупателя, пользователь смог бы выбрать только саму ссылку, но не смог бы вытянуть в отчет ЗаказПокупателя.Дата или ЗаказПокупателя.Контрагент.
Выясним причину, по которой условия {ГДЕ ...} часто ставят в самом конце запроса к виртуальной таблице или вложенному запросу. Если мы используем {ГДЕ ...} во вложенном запросе, СКД постарается применить этот фильтр как можно раньше — непосредственно при выборке данных из таблиц БД. Это критически важно для производительности. Если мы наложим условие только на самом верхнем уровне (уже после всех объединений и группировок), СУБД сначала прочитает все данные, объединит их, сгруппирует и только потом отсеет лишнее. Использование фигурных скобок во вложенных частях позволяет СКД внедрить условие внутрь каждой ветки ОБЪЕДИНИТЬ ВСЕ.
Рассмотрим сценарий, когда флаг Автозаполнение выключен. В этом режиме на закладке «Наборы данных» список доступных полей пуст, пока мы не опишем их в тексте запроса через фигурные скобки или не добавим вручную в таблицу полей.
Когда мы пишем конструкцию {ВЫБРАТЬ ЗаказПокупателя.*} во вложенном запросе, мы явно регистрируем это поле в системе компоновки. Это позволяет использовать его в качестве источника для полей верхнего уровня. Если вложенный запрос большой и сложный, такой явный маппинг гарантирует, что связь между внутренним полем и полем, доступным пользователю в настройках, не разорвется.
Посмотрим на процесс генерации запроса глазами системы. Допустим, пользователь в настройках отчета выбрал только поле Количество.
Сумма, СуммаОтгружено и прочие не требуются ни для вывода, ни для группировок, ни для отборов.{ВЫБРАТЬ...} во всех вложенных запросах.NULL или просто исключает из списка SELECT, если это возможно.Важный момент: если поле описано в обычной секции ВЫБРАТЬ, но отсутствует в расширении {ВЫБРАТЬ...}, оно будет рассчитываться СУБД всегда, вне зависимости от настроек пользователя. Именно поэтому опытные разработчики всегда дублируют список значимых полей в фигурных скобках, особенно если расчет этих полей ресурсоемок. Для отладки сложных запросов и проверки текстов схем компоновки данных подойдет инженерная консоль запросов для 1С.
Подведем итоги и сформируем правила эффективного использования расширений во вложенных структурах:
{ВЫБРАТЬ...} во вложенных запросах для полей, расчет которых требует значительных ресурсов (сложные формулы, соединения).ОБЪЕДИНИТЬ ВСЕ, не ленитесь прописывать фигурные скобки в каждой части объединения. Это даст СКД возможность оптимизировать каждую ветку по отдельности.Поле.*, чтобы предоставить пользователю возможность обращаться к свойствам ссылочных типов (через точку).ВТ_Остатки.Количество КАК Кол {ВЫБРАТЬ Кол КАК ОстатокНаСкладе}.Таким образом, фигурные скобки во вложенных запросах — это мощный механизм управления производительностью и гибкостью отчета. Они позволяют превратить статический SQL-код в интеллектуальную структуру, которая адаптируется под конкретные нужды пользователя в момент формирования отчета.