Как работают фигурные скобки во вложенных запросах СКД

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

Система компоновки данных (СКД) в 1С — это не просто построитель отчетов, а мощный генератор запросов, который на лету изменяет исходный текст запроса в зависимости от настроек пользователя. Одним из самых загадочных инструментов для начинающих (и не только) разработчиков являются расширения языка запросов, заключаемые в фигурные скобки {}. Особенно много вопросов вызывает их использование внутри вложенных запросов. Разберем детально, зачем это нужно и как это работает, в том числе когда используется пользовательская СКД. Для интерактивной настройки и построения отчетов на стороне клиентского приложения можно использовать инструмент «Пользовательская СКД».

Основы расширения языка запросов СКД

Для начала вспомним, что фигурные скобки в СКД — это инструкции для процессора компоновки данных. Когда мы пишем обычный запрос, он статичен. Но как только мы добавляем расширения, задействуя процессор схемы запроса, мы говорим системе: «Если пользователь выбрал это поле, добавь его в реальный запрос к базе данных, а если не выбрал — удали». Рассмотрим основные секции расширений:

Теперь проанализируем ситуацию, когда эти конструкции встречаются внутри подзапроса или объединения (ОБЪЕДИНИТЬ ВСЕ). На первый взгляд кажется, что это дублирование, но это далеко не так.

Зачем нужны фигурные скобки во вложенном запросе

Разберем конкретный пример из практики, когда в СКД снят флаг Автозаполнение. Это ситуация, когда разработчик берет на себя полную ответственность за описание полей компоновки. Если мы не укажем расширения во вложенном запросе, СКД может просто «не увидеть» поля, которые находятся внутри него, или не сможет эффективно пробросить туда отборы.

Основные причины использования {ВЫБРАТЬ...} внутри подзапроса:

  1. Динамическое «усечение» запроса (Pruning). Это самая важная функция для производительности. Если в подзапросе вычисляется 10 полей, но пользователь в отчете вывел только 2, СКД благодаря фигурным скобкам может физически исключить расчет остальных 8 полей из итогового SQL-запроса к СУБД. Это экономит ресурсы и позволяет реализовать принцип нет данных — нет столбцов.
  2. Связывание полей при отключенном автозаполнении. Когда автозаполнение выключено, фигурные скобки служат явным указателем: «Это поле внутреннего запроса соответствует полю компоновки на верхнем уровне». Без этого механизма сложные отчеты с вложенными структурами часто выдают ошибки или не позволяют накладывать отборы на внутренние таблицы.
  3. Оптимизация конструкций ОБЪЕДИНИТЬ ВСЕ. В запросах с объединением нескольких таблиц СКД может оптимизировать каждую ветку отдельно. Если поле СуммаОплаченоПоставщикам нужно только в одной части объединения и пользователь его не выбрал, расширение позволит системе «вырезать» лишнюю логику только из этой части.

Разбор практического примера кода

Рассмотрим фрагмент запроса, который вызвал вопросы. Обратим внимание на то, как структурированы вложенные поля:


ВЫБРАТЬ
    ВложеныйЗапрос.ЗаказПокупателя КАК ЗаказПокупателя,
    ВложеныйЗапрос.Номенклатура КАК Номенклатура,
    СУММА(ВложеныйЗапрос.Количество) КАК Количество,
    СУММА(ВложеныйЗапрос.Сумма) КАК Сумма,
    СУММА(ВложеныйЗапрос.КоличествоОтгружено) КАК КоличествоОтгружено,
    СУММА(ВложеныйЗапрос.СуммаОтгружено) КАК СуммаОтгружено,
    СУММА(ВложеныйЗапрос.СуммаРасход) КАК СуммаРасход,
    СУММА(ВложеныйЗапрос.СуммаОплаченоПоставщикам) КАК СуммаОплаченоПоставщикам
    {ВЫБРАТЬ ЗаказПокупателя.*, Номенклатура.*, Количество, Сумма, КоличествоОтгружено, СуммаОтгружено, СуммаРасход, СуммаОплаченоПоставщикам}
ИЗ (
    ВЫБРАТЬ
        ВТ_Остатки.ЗаказПокупателя КАК ЗаказПокупателя,
        ВТ_Остатки.Номенклатура КАК Номенклатура,
        СУММА(ВТ_Остатки.Количество) КАК Количество,
        СУММА(ВТ_Заказы.Цена * ВТ_Остатки.Количество) КАК Сумма,
        0 КАК КоличествоОтгружено,
        0 КАК СуммаОтгружено,
        0 КАК СуммаРасход,
        0 КАК СуммаОплаченоПоставщикам
        {ВЫБРАТЬ ЗаказПокупателя.*, Номенклатура.*, Количество, Сумма, КоличествоОтгружено, СуммаОтгружено, СуммаРасход КАК СуммаРасход, СуммаОплаченоПоставщикам}
    ИЗ ВТ_Остатки КАК ВТ_Остатки
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Заказы КАК ВТ_Заказы ПО ВТ_Остатки.ЗаказПокупателя = ВТ_Заказы.ЗаказПокупателя И ВТ_Остатки.Номенклатура = ВТ_Заказы.Номенклатура
    СГРУППИРОВАТЬ ПО ВТ_Остатки.ЗаказПокупателя, ВТ_Остатки.Номенклатура
) КАК ВложеныйЗапрос
{ГДЕ ВложеныйЗапрос.ЗаказПокупателя.*, ВложеныйЗапрос.Номенклатура.*}
СГРУППИРОВАТЬ ПО ВложеныйЗапрос.Номенклатура, ВложеныйЗапрос.ЗаказПокупателя

Проанализируем ситуацию: здесь мы видим использование {ВЫБРАТЬ ...} как во внешнем запросе, так и во вложенном. Рассмотрим подробнее, что дает конструкция ЗаказПокупателя.*. Символ «звездочка» после поля в фигурных скобках сообщает СКД, что пользователю должны быть доступны для выбора все дочерние реквизиты этого объекта. Если бы мы написали просто ЗаказПокупателя, пользователь смог бы выбрать только саму ссылку, но не смог бы вытянуть в отчет ЗаказПокупателя.Дата или ЗаказПокупателя.Контрагент.

Механизм проброса условий ГДЕ

Выясним причину, по которой условия {ГДЕ ...} часто ставят в самом конце запроса к виртуальной таблице или вложенному запросу. Если мы используем {ГДЕ ...} во вложенном запросе, СКД постарается применить этот фильтр как можно раньше — непосредственно при выборке данных из таблиц БД. Это критически важно для производительности. Если мы наложим условие только на самом верхнем уровне (уже после всех объединений и группировок), СУБД сначала прочитает все данные, объединит их, сгруппирует и только потом отсеет лишнее. Использование фигурных скобок во вложенных частях позволяет СКД внедрить условие внутрь каждой ветки ОБЪЕДИНИТЬ ВСЕ.

Особенности работы при отключенном автозаполнении

Рассмотрим сценарий, когда флаг Автозаполнение выключен. В этом режиме на закладке «Наборы данных» список доступных полей пуст, пока мы не опишем их в тексте запроса через фигурные скобки или не добавим вручную в таблицу полей.

Когда мы пишем конструкцию {ВЫБРАТЬ ЗаказПокупателя.*} во вложенном запросе, мы явно регистрируем это поле в системе компоновки. Это позволяет использовать его в качестве источника для полей верхнего уровня. Если вложенный запрос большой и сложный, такой явный маппинг гарантирует, что связь между внутренним полем и полем, доступным пользователю в настройках, не разорвется.

Как СКД формирует итоговый SQL-запрос

Посмотрим на процесс генерации запроса глазами системы. Допустим, пользователь в настройках отчета выбрал только поле Количество.

  1. СКД анализирует схему и видит, что поля Сумма, СуммаОтгружено и прочие не требуются ни для вывода, ни для группировок, ни для отборов.
  2. Система просматривает расширения {ВЫБРАТЬ...} во всех вложенных запросах.
  3. Если эти поля обернуты в фигурные скобки, СКД заменяет их в итоговом тексте на NULL или просто исключает из списка SELECT, если это возможно.
  4. В результате база данных выполняет гораздо более легкий запрос, не тратя время на умножение цены на количество или обращение к связанным таблицам для получения данных, которые все равно будут отброшены.

Важный момент: если поле описано в обычной секции ВЫБРАТЬ, но отсутствует в расширении {ВЫБРАТЬ...}, оно будет рассчитываться СУБД всегда, вне зависимости от настроек пользователя. Именно поэтому опытные разработчики всегда дублируют список значимых полей в фигурных скобках, особенно если расчет этих полей ресурсоемок. Для отладки сложных запросов и проверки текстов схем компоновки данных подойдет инженерная консоль запросов для 1С.

Рекомендации по использованию

Подведем итоги и сформируем правила эффективного использования расширений во вложенных структурах:

Таким образом, фигурные скобки во вложенных запросах — это мощный механизм управления производительностью и гибкостью отчета. Они позволяют превратить статический SQL-код в интеллектуальную структуру, которая адаптируется под конкретные нужды пользователя в момент формирования отчета.

← На главную