В процессе разработки отчетов на базе Системы компоновки данных (СКД) в 1С можно столкнуться со специфическими, на первый взгляд нелогичными конструкциями в текстах запросов. Одной из таких загадочных инструкций является передача значения в фигурных скобках с псевдонимом в качестве параметра периода виртуальной таблицы, например: {Неопределено КАК Поле2} в параметрах метода СрезПоследних(). В этой статье мы подробно разберем, зачем опытные разработчики используют этот прием, как он устроен "под капотом" платформы «1С:Предприятие 8» и какие архитектурные проблемы он помогает решить.
Для того чтобы понять природу возникновения этой конструкции, проанализируем поведение системы компоновки данных при работе со встроенным механизмом автозаполнения. Когда мы создаем набор данных типа «Запрос» и оставляем включенным флаг «Автозаполнение» (что делается в 95% случаев для экономии времени), СКД берет на себя управление параметрами запроса.
Если в тексте запроса используется виртуальная таблица среза последних или остатков, например:
Выбрать
ВалютыСрезПоследних.Валюта,
ВалютыСрезПоследних.Курс
Из
РегистрСведений.КурсыВалют.СрезПоследних() Как ВалютыСрезПоследних
Препроцессор СКД автоматически модифицирует этот запрос перед отправкой в СУБД. Платформа принудительно подставит в параметры виртуальной таблицы глобальный параметр периода. Итоговый запрос будет выглядеть примерно так: РегистрСведений.КурсыВалют.СрезПоследних(&Период). Это поведение влечет за собой две серьезные проблемы:
&Период. Пользователь увидит его на форме настроек отчета, даже если по бизнес-логике ввод даты для этой таблицы не предполагался.Выясним причину, почему именно выражение {Неопределено КАК Поле2} решает описанные проблемы. Разберем эту синтаксическую конструкцию по элементам:
{}: Это расширение языка запросов, предназначенное специально для СКД. Все, что написано внутри фигурных скобок, является необязательной (компонуемой) частью запроса. Препроцессор СКД анализирует эти блоки отдельно. Наличие фигурных скобок в параметрах виртуальной таблицы явно указывает системе: «Разработчик сам управляет поведением этого параметра, автоматическое заполнение здесь применять не нужно». Благодаря этому СКД отключает принудительную подстановку стандартного параметра &Период для данной таблицы.Неопределено: Передача пустого значения или типа Неопределено в параметр периода виртуальной таблицы указывает платформе на необходимость получения "самого последнего" среза (на максимальную дату, существующую в базе данных). Так как здесь нет символа амперсанда &, СКД понимает, что реального параметра в схему добавлять не нужно. Вкладка параметров отчета остается чистой.КАК Поле2 (псевдоним): Это технический "хак", необходимый для корректной работы Конструктора запросов 1С. Парсер конструктора запросов ожидает, что любое выражение внутри фигурных скобок в полях параметров должно быть описано как поле компоновки данных с указанием его псевдонима. Если написать просто {Неопределено}, Конструктор запросов при попытке сохранить или открыть схему выдаст синтаксическую ошибку. Указание фиктивного псевдонима КАК Поле2 (или любого другого имени) позволяет успешно пройти проверку синтаксиса в визуальном редакторе.В момент компоновки макета и генерации финального SQL-запроса СКД анализирует фигурные скобки. Видя, что внутри передано фиксированное значение Неопределено, не привязанное к пользовательским настройкам, СКД просто удаляет эту конструкцию из итогового текста. На уровне СУБД выполняется чистый запрос без ограничений по периоду, гарантирующий получение самого актуального среза.
Рассмотрим подробнее другие способы решения этой проблемы, чтобы понять, почему опытные разработчики все же предпочитают использовать конструкцию с Неопределено:
Автозаполнение для всего набора данных. Однако в этом случае разработчику придется вручную настраивать роли всех полей, описывать доступные поля выбора, отборы и параметры. Для сложных запросов это колоссальный объем рутинной работы, поэтому ради одной виртуальной таблицы отключать автозаполнение нерационально.СрезПоследних(&ТехническийПериод). Затем на вкладке «Параметры» в СКД для параметра &ТехническийПериод установить флаг «Ограничение доступности» (чтобы скрыть его от пользователя) и жестко прописать в качестве значения пустую дату или значение Неопределено. Этот способ абсолютно рабочий, но он требует выполнения лишних действий в нескольких вкладках конструктора и оставляет в схеме неиспользуемый технический параметр.Неопределено без фигурных скобок: Написание СрезПоследних(Неопределено) без фигурных скобок лишает запрос гибкости. На некоторых версиях СУБД или старых релизах платформы прямая передача литерала Неопределено в качестве даты может вызывать ошибки приведения типов на уровне базы данных или приводить к неоптимальному плану выполнения запроса.Проанализируем практическую ситуацию. Представим, что мы разрабатываем отчет по продажам за произвольный период, в котором также нужно вывести самую актуальную цену номенклатуры (действующую на текущий момент времени, а не на момент продажи). Нам необходимо соединить обороты продаж с актуальным срезом цен.
Для решения этой задачи мы напишем следующий запрос:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура КАК Номенклатура,
ПродажиОбороты.КоличествоОборот КАК Количество,
ЦеныНоменклатурыСрезПоследних.Цена КАК АктуальнаяЦена
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних({Неопределено КАК Поле2}, ) КАК ЦеныНоменклатурыСрезПоследних
ПО ПродажиОбороты.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
В данном примере СКД автоматически создаст параметры &НачалоПериода и &КонецПериода для ограничения данных таблицы оборотов продаж. При этом благодаря конструкции {Неопределено КАК Поле2} виртуальная таблица цен не будет ограничена периодом отчета, и система вернет самую последнюю цену из базы данных для каждой номенклатуры.
Использование этого приема позволяет сохранить лаконичность настроек схемы компоновки данных, не перегружая интерфейс пользователя лишними параметрами и гарантируя корректность получаемых данных.