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