Что означают фигурные скобки в запросах 1С и как их отлаживать

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

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

Назначение фигурных скобок в языке запросов

Фигурные скобки {} представляют собой специальное расширение языка запросов платформы 1С:Предприятие для системы компоновки данных (СКД) и построителя отчетов. Стандартная СУБД ничего не знает о фигурных скобках, поэтому платформа 1С обрабатывает такой запрос до передачи в базу данных.

Главная функция фигурных скобок — объявление необязательных (опциональных) элементов запроса. Рассмотрим основные сценарии их применения:

  1. Необязательные параметры виртуальных таблиц. Если параметр заключен в скобки, например {(&НачалоПериода)}, то СКД подставляет его в итоговый запрос к СУБД только тогда, когда соответствующий параметр заполнен или включен в настройках отчета. Если пользователь не заполнил дату, СКД просто уберет этот параметр из вызова виртуальной таблицы, не вызывая синтаксическую ошибку отсутствия значения.
  2. Необязательные условия и отборы. Конструкции в предложении ГДЕ {ГДЕ ...} позволяют динамически внедрять фильтры только при их активации пользователем в пользовательских настройках.
  3. Связывание полей и псевдонимов. В параметрах виртуальных таблиц через фигурные скобки часто передается список доступных для фильтрации полей: {(Фирма) КАК Организация, (Субконто1).* КАК Контрагент}. Это указывает компоновщику, как пользовательские отборы должны сопоставляться с реальными полями и субконто регистра.

Посмотрим на пример из исходного запроса:


ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
        {(&НачалоПериода)}, 
        {(&КонецПериода)}, , , 
        Счет В ИЕРАРХИИ (&СчетаДебиторов), 
        &ВидыСубконтоКД, 
        {(Фирма) КАК Организация, (Субконто1).* КАК Контрагент, (Субконто2).* КАК Договор}
    ) КАК ОстаткиИОбороты

Здесь параметры периода являются опциональными, а в последнем параметре виртуальной таблицы настроено сопоставление полей: если пользователь задаст отбор по полю «Организация», СКД автоматически транслирует его в условие по полю «Фирма» непосредственно внутри виртуальной таблицы, что обеспечивает максимальную производительность выборки на уровне СУБД.

Что означает звездочка в конструкции вида (Субконто1).* КАК Контрагент

Выясним причину использования точки со звездочкой .*. Данный синтаксис указывает СКД, что доступно не только само ссылочное поле, но и все его реквизиты (через точку):

  1. Доступность реквизитов в отборе: Конструкция (Субконто1).* КАК Контрагент сообщает компоновщику, что в отборах отчета пользователь может выбирать реквизиты контрагента (например, «Контрагент.ИНН», «Контрагент.ГоловнойКонтрагент» или «Контрагент.ЮрФизЛицо»).
  2. Оптимизация на уровне СУБД: Если пользователь устанавливает фильтр по реквизиту субконто (например, выбирает только контрагентов с определенным ИНН), платформа встроит это условие прямо в параметры виртуальной таблицы регистра. За счет этого СУБД отфильтрует записи еще на этапе расчета остатков и оборотов, а не будет выбирать всю таблицу с последующей фильтрацией через ГДЕ.

Как отлаживать запрос с фигурными скобками

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

  1. Ручная адаптация для обычной консоли запросов. Чтобы быстро проверить логику запроса в классической консоли, необходимо убрать расширения СКД: удалить фигурные скобки и псевдонимы со звездочками. Например, вместо {(&НачалоПериода)} указать стандартный параметр &НачалоПериода, а список условий в последнем параметре заменить на жестко прописанные условия или оставить пустым.
  2. Использование консоли компоновки данных. Для полноценной отладки запросов со всеми директивами компоновщика следует использовать специализированные инструменты (например, консоль компоновки данных из подсистемы «Инструменты разработчика»). В такой консоли можно загрузить схему компоновки напрямую из отчета с помощью функции выбора по метаданным.
  3. Программный вызов отладки через точку останова. В «Инструментах разработчика» предусмотрены специальные сервисные функции, которые можно вызвать в окне вычисления выражений при остановке на точке останова:
    
    Отладить(СхемаКомпоновки, Истина)
    // или сокращенный синтаксис:
    От(СхемаКомпоновки)
    
    Этот вызов открывает схему в отдельном окне инструмента, сбрасывая ограничения доступности параметров и позволяя протестировать генерацию результирующего запроса.
  4. Получение реального текста запроса из макета компоновки. Чтобы увидеть точный текст SQL-запроса, сформированный платформой с учетом пользовательских настроек, проанализируем свойство макета компоновки в коде:
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
    
    // Получаем итоговый запрос без фигурных скобок для первого набора данных:
    ТекстИтоговогоЗапроса = МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос;
    
    Полученный текст можно без ошибок выполнять в любой стандартной консоли запросов.

Реализация задачи: вывод задолженности и последнего документа движения

В регистрах бухгалтерии виртуальная таблица остатков не содержит информации о регистраторах. Чтобы вывести долг контрагента и одновременно показать последний документ, выполнивший движение, рассмотрим два надежных способа реализации в СКД.

  1. Использование двух наборов данных в СКД. Это наиболее производительный и чистый подход.

    Создадим два набора данных типа «Запрос»:

    Набор данных 1 (Остатки): выбирает текущую задолженность по контрагентам из виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.Остатки.

    Набор данных 2 (Последнее движение): выбирает регистратор и период движения с ограничением по счету и контрагенту.

    На вкладке «Связи наборов данных» свяжем Набор данных 1 с Набором данных 2 по полю «Контрагент», передав значение контрагента в параметры второго набора. В этом случае компоновщик автоматически выполнит выборку регистратора только для тех контрагентов, по которым есть остаток задолженности.

  2. Один запрос с соединением по максимальной дате движения. Если требуется объединить данные внутри одного запроса, соединим таблицу остатков со сгруппированной таблицей движений:
    
    ВЫБРАТЬ
        Остатки.Организация КАК Организация,
        Остатки.Субконто1 КАК Контрагент,
        Остатки.СуммаОстаток КАК СуммаДолга,
        Движения.Регистратор КАК ПоследнийДокумент
    ИЗ
        РегистрБухгалтерии.Хозрасчетный.Остатки(
            &Период, 
            Счет В ИЕРАРХИИ (&СчетаДебиторов), 
            &ВидыСубконто, 
            Организация = &Организация
        ) КАК Остатки
        ЛЕВОЕ СОЕДИНЕНИЕ (
            ВЫБРАТЬ
                МаксДвижения.Субконто1 КАК Контрагент,
                МАКСИМУМ(ДвиженияРегистра.Регистратор) КАК Регистратор
            ИЗ
                (
                    ВЫБРАТЬ
                        Субконто1 КАК Субконто1,
                        МАКСИМУМ(Период) КАК МаксПериод
                    ИЗ
                        РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
                            , 
                            &Период, 
                            Счет В ИЕРАРХИИ (&СчетаДебиторов) И Организация = &Организация, 
                            , 
                        )
                    СГРУППИРОВАТЬ ПО
                        Субконто1
                ) КАК МаксДвижения
                ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
                    , 
                    &Период, 
                    Счет В ИЕРАРХИИ (&СчетаДебиторов) И Организация = &Организация, 
                    , 
                ) КАК ДвиженияРегистра
                ПО МаксДвижения.Субконто1 = ДвиженияРегистра.Субконто1
                И МаксДвижения.МаксПериод = ДвиженияРегистра.Период
            СГРУППИРОВАТЬ ПО
                МаксДвижения.Субконто1
        ) КАК Движения
        ПО Остатки.Субконто1 = Движения.Контрагент
    

    Важное замечание: При соединении с таблицей движений обязательно накладывайте жесткие условия по счетам и организации в параметрах виртуальной таблицы движений, чтобы исключить сканирование избыточных записей регистра в базе данных.

← На главную