Работа с моделью запроса

29.03.26

Разработка - Инструментарий разработчика

Представляю новую версию подсистемы работы со схемой запроса, которая завершает её эволюцию от библиотеки по работе со схемой запроса до объектной реализации модели запроса 2. Теперь есть выбор между классическим и текучим стилем написанию кода - оба варианта взаимозаменяемы. Ключевое улучшение - использование объектов в качестве источников данных, значений полей и параметров в условиях виртуальных таблиц, а также новые операторы позиционирования в схеме

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
KASL_Demo
.dt 381,83Mb
1 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Оглавление:


От текста запроса к объектной модели


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

Объектная модель запроса поднимает уровень абстракции при работе с запросом 1С. В этой парадигме запрос 1С перестаёт быть просто строкой - он превращается в составной объект, отдельные части которого можно изменять независимо: источники и их поля, отборы и соединения, запросы в пакете и их колонки.

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

Такая модель есть в платформе 1С начиная с версии 8.3.5 - это Схема запроса. Она позволяет при динамическом построении запроса оперировать не фрагментами текста, а логикой структурного построения. Кроме того, отпадает необходимость в манипуляциях параметрами запроса для изменения логики его работы (параметры-переключатели). Программное формирование текста через объектную модель даёт код, подчинённый логике запроса, что упрощает отладку, снижает затраты на сопровождение и изменение. Отказ от параметров-переключателей также положительно сказывается на производительности выполнения запроса.

Однако при работе с объектом Схема запроса важно учитывать одну поведенческую особенность. На программном уровне этот объект ведёт себя аналогично интерактивному конструктору запросов. Например, при добавлении таблицы конструктор может автоматически создать связи по совпадающим полям подходящих типов. С точки зрения разработчика такое автоматическое поведение не всегда ожидаемо: добавление источника не должно неявно порождать связи. С другой стороны, при удалении временной таблицы или поля вполне логично, что все ссылки на этот источник или удалённые поля будут очищены, а соответствующие связи удалены. Также при использовании агрегатных функций в полях выборки автоматически добавляются поля группировки.

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

Код построения запроса с использованием объекта Схема запроса зачастую оказывается избыточным. Причина - необходимость явно формировать контекст для каждого элемента: выделять запрос из пакета, оператор из запроса, поле - из источника и колонки запроса и так далее.

Для сокращения избыточности была создана библиотека РаботаСоСхемойЗапроса. В процессе её применения возникли идеи по дальнейшему упрощению: введение шорткатов, обращение к результатам запроса по имени, условных полей, параметров из окружения и т.д.. Для реализации этих идей была разработана объектная модель запроса , расширяющая возможности исходной библиотеки.

В последней версии объектной модели были объединены функциональные возможности библиотеки РаботаСоСхемойЗапроса и МодельЗапроса в одну библиотеку РаботаСМодельюЗапроса. Результатом такого объединения стала более простая реализация расширения функциональности встроенной Схемы запроса и, как побочный эффект, возможность использовать на выбор классический и объектный стиль текучего интерфейса.

На следующем этапе библиотека была полностью переписана с включением всего нового функционала объектной реализации. В результате прежняя библиотека была заменена на новую версию — «РаботаСМодельюЗапроса». Дальнейший эксперимент показал, что код библиотеки можно конвертировать непосредственно в объектную модель. Так возникла и объектная модель 2, которая напрямую работает со схемой запроса, выступая в роли её расширения.

Дуальный интерфейс


Модель запроса построена по классическому принципу паттерна «Строитель». Существует два основных подхода к его реализации:

  • Классический стиль: Методы API последовательно вызываются с явной передачей создаваемого объекта в каждый метод.
  • Стиль текучего интерфейса: Методы конфигурации возвращают сам объект-строитель, что позволяет объединять вызовы в непрерывную цепочку, удобную для чтения и написания. Назовем этот стиль Объектным.

Код 1С. Классический стиль

// ЗАПРОС ПАКЕТА. _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты
РаботаСМодельюЗапроса.ЗапросПакета(МодельЗапроса, "_ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты");
РаботаСМодельюЗапроса.Выбрать(МодельЗапроса);
РаботаСМодельюЗапроса.Источник(МодельЗапроса, "РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.ОстаткиИОбороты");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "Номенклатура");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "МестоХранения");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "Организация");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "КоличествоНачальныйОстаток");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "КоличествоКонечныйОстаток");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "КоличествоОборот");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "КоличествоПриход");
РаботаСМодельюЗапроса.Поле(МодельЗапроса, "КоличествоРасход");

Код 1С. Стиль текучего интерфейса

;// ЗАПРОС ПАКЕТА. _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты
МодельЗапроса.ЗапросПакета("_ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты")
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.ОстаткиИОбороты")
        .Поле("Номенклатура")
        .Поле("МестоХранения")
        .Поле("Организация")
        .Поле("КоличествоНачальныйОстаток")
        .Поле("КоличествоКонечныйОстаток")
        .Поле("КоличествоОборот")
        .Поле("КоличествоПриход")
        .Поле("КоличествоРасход")
;

Обе версии МоделиЗапроса — классическая и в текучем стиле — имеют идентичную функциональность. Они выполняют одни и те же задачи, а разница заключается лишь во внутреннем устройстве и синтаксисе:

  • Классическая реализация оперирует структурой данных, в которой хранится текущее состояние.
  • Стиль текучего интерфейса использует обработку как объект и работает по принципу изменения состояния объекта.

Выбор модели определяется тем, какой конструктор вы вызываете:

// Классическая модель
МодельЗапроса = РаботаСМодельюЗапроса.НовыйМодельЗапроса();
// Объектная модель
МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();

Между этими реализациями нет разницы ни в функциональности, ни в производительности. Выбор между ними — вопрос предпочтения.

  • Классический стиль:
    • Преимущество: проще в отладке, так как каждый метод вызывается отдельной строкой
    • Недостаток: код избыточен из-за необходимости постоянного обращение к модулю и передачи одной и той же структуры в каждый метод
  • Текучий интерфейс или объектная модель:
    • Преимущество: более лаконичный и легче читается, так как вызовы методов объединяются в непрерывную цепочку
    • Недостаток: сложнее отлаживать, потому что нельзя установить точку останова на промежуточном методе в середине цепочки. Требуются дополнительные права на использование обработки

Далее в примерах я буду отдавать предпочтение объектной модели в текучем интерфейсе. Однако весь представленный код будет абсолютно аналогично работать и с классическими вызовами.

Первой моей задумкой было реализовать всю функциональность в классическом стиле, а затем сконвертировать ее в объектную реализацию. В принципе эта задача решаема, но пока я остановился на ручном дублировании кода из одной реализации в другую. Недостаток такого подхода в том, что предпочтительная реализация начинает убегать вперед, а менее предпочтительная начинает отставать в своей функциональности. Однако принципиально обе версии реализации эквивалентны: в классической для хранения контекста используется структура, а в объектной - обработка.

Выбор стиля

Выбор стиля

Работа с моделью запроса


Конструктор

Модель поддерживает несколько способов инициализации. Для объектной модели инициализацию можно выполнить непосредственно в конструкторе.

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

Код 1С. Классическая инициализация

УстановитьТекстЗапроса(МодельЗапроса, ТекстЗапроса);
УстановитьЗапрос(МодельЗапроса, НовыйЗапрос);
УстановитьМенеджерВременныхТаблиц(МодельЗапроса, НовыйМенеджерВременныхТаблиц);
УстановитьСхемуЗапроса(МодельЗапроса, НоваяСхемаЗапроса);
УстановитьСхемуКомпоновкиДанных(МодельЗапроса, Схема, Настройки);
УстановитьСхемуТаблицыСписка(МодельЗапроса, ТаблицаСписка);
УстановитьСхемуДинамическогоСписка(МодельЗапроса, Список)

Код 1С. Конструкторы модели запроса

МодельЗапроса();
МодельЗапроса(ТекстЗапроса);
МодельЗапроса(СхемаСКД, НастройкиСКД);
МодельЗапроса(ТаблицаФормы);
МодельЗапроса(ДинамическийСписок);
МодельЗапроса(Запрос);
МодельЗапроса(СхемаЗапроса, МенеджерВременныхТаблиц);
МодельЗапроса(МенеджерВременныхТаблиц);

Модификация схемы

Чтобы изменить существующий запрос, используемый моделью, сначала нужно выбрать конкретный элемент его структуры. Это может быть запрос внутри пакета, оператор или источник данных.

После позиционирования можно вносить точечные изменения и продолжать построение запроса с нужного места.

Для позиционирования используется индекс элемента. Кроме того, можно использовать:

  • Для запроса в пакете: имя временной таблицы
  • Для источника данных: его псевдоним или имя таблицы
  • Для оператора по умолчанию устанавливается позиция первого в позиционированном запросе

Код 1С. Установка позиции

МодельЗапроса.УстановитьЗапросПакета(ИндексИлиИмяВременнойТаблицы);
МодельЗапроса.УстановитьОператор(Индекс);
МодельЗапроса.УстановитьИсточник(ИндексИлиПсевдоним);

Код 1С. Модификация

// Заменить
МодельЗапроса.ЗаменитьИсточник(ПседонимИсточника, Таблица, НовыйПсевдоним);
// Удалить
МодельЗапроса.УдалитьИсточник(Индекс);
МодельЗапроса.УдалитьКолонку(Псевдоним);
МодельЗапроса.УдалитьПоле(Псевдоним);
// Очистить
МодельЗапроса.ОчиститьОтбор();
МодельЗапроса.ОчиститьГруппировки();
МодельЗапроса.ОчиститьИтоги();
МодельЗапроса.ОчиститьСоединения();

Добавление копированием: запрос, оператор выбрать

Чтобы упростить код, используем копирование. С его помощью можно дублировать уже описанный запрос пакета или оператор выбора в текущем запросе. Это удобно, когда структура запросов или операторов часто повторяется. Тогда код модели запроса становится заметно короче.

  • ЗапросПакета(, , ИндексКопии);// в качестве индекса можно использовать: индекс запроса, имя запроса, текст запроса
  • Выбрать(, , , ИндексКопии)

Код 1С. Добавление схемы копированием

МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
МодельЗапроса.ЗапросПакета(,, "ВЫБРАТЬ 1 ПОМЕСТИТЬ ВТ");
МодельЗапроса.ЗапросПакета(,, "ВЫБРАТЬ 1")
    .ОбъединитьВсе(,, 0)
;
МодельЗапроса.ЗапросПакета(,, "ВТ").Поместить("ВТ2");
ТекстЗапроса = МодельЗапроса.ТекстЗапроса();

Запрос 1С. Результат добавления копированием

ВЫБРАТЬ
    1 КАК Поле1
ПОМЕСТИТЬ ВТ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    1 КАК Поле1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    1 КАК Поле1
ПОМЕСТИТЬ ВТ2

Именованные результаты пакета запросов

При формировании пакета запросов имена запросов, помещаемых во временные таблицы, присваиваются автоматически; их можно задать явно в операторе ЗапросПакета(ИмяЗапроса). После выполнения к результату можно обратиться по этому имени.

Код 1С. Именованные запросы

;// ЗАПРОС ПАКЕТА. ВТ_ИЗМЕРЕНИЯ
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ИЗМЕРЕНИЯ")
    .Выбрать()
    ...
;// ЗАПРОС ПАКЕТА. _ДемоОстаткиТоваровВМестахХраненияОстатки
МодельЗапроса.ЗапросПакета("_ДемоОстаткиТоваровВМестахХраненияОстатки")
    .Выбрать()
    ...
;
МодельЗапроса.ВыполнитьЗапрос();
Результат = МодельЗапроса.Результат("ВТ_ИЗМЕРЕНИЯ");
Результат = МодельЗапроса.Результат("_ДемоОстаткиТоваровВМестахХраненияОстатки");

Особенности работы с временными таблицами

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

Однако в задачах на модификацию запроса могут встречаться варианты, когда схема создана из текста запроса. В этом случае перед использованием временной таблицы необходимо описать её доступные поля. Это необходимо потому что другого источника информации о таблице у схемы запроса просто нет.

Если же производится чтение таблицы из объекта, то здесь нет необходимости описывать поля, т.к. будут прочитаны ровно те поля, которые указаны или получены из метаданных объекта. Единственное ограничение возникает в том, что необходимо явно указать в поле выбора имя псевдонима источника.

Последнее замечание относится к стандартному поведению платформы 1С. Если вы читаете данные из объекта, то необходимо явно указывать псевдоним источника в полях выбора.

Код 1С. Доступные поля временной таблицы

// конструктор из текста запроса
МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса(ТекстЗапроса)
;
МодельЗапроса.ЗапросПакета()
    .Источник("ВТ_ДАННЫЕ") // временная таблица, которая будет в реальном запросе
        .ДоступноеПоле("Ссылка")
        .ДоступноеПоле("Организация", Тип("СправочникСсылка._ДемоОрганизации"))
    .Поле("Ссылка")
    .Поле("Организация.Код", "Код") // вложенное поле из типа
;

Код 1С. Чтение из объекта

МодельЗапроса.ЗапросПакета().Поместить("ВТ_ТАБЛИЦА")
    .Источник("&Таблица") // чтение из объекта
        .ДоступноеПоле("Ссылка")
        .ДоступноеПоле("Организация", Тип("СправочникСсылка._ДемоОрганизации"))
    .Поле("ВТ_ТАБЛИЦА.Ссылка") // обязательное указание псевдонима
    .Поле("ВТ_ТАБЛИЦА.Организация") // не допускаются вложенные поля
;
МодельЗапроса.ЗапросПакета()
    .Источник("ВТ_ТАБЛИЦА")
    .Поле("Организация.Код")// можно обратиться к вложенному полю из соответствующего типа
;

Тернарный оператор и признак действия

Некоторые операторы поддерживают условное применение с выбором: УсловноеПоле, УсловныйОтбор; у остальных (Условие, Отбор) можно задать признак действия.

Код 1С. Условные операторы: условие с выбором или признак действия

// Тернарный оператор
МодельЗапроса.УсловноеПоле(Выражение, ВыражениеИстина, ВыражениеЛожь, Псевдоним);
МодельЗапроса.УсловныйОтбор(Выражение, ВыражениеИстина, ВыражениеЛожь);
// Действует
МодельЗапроса.Условие(Выражение, Действует = Истина);
МодельЗапроса.Отбор(Выражение, Действует = Истина);

УсловиеВхождения

Операторы вхождения позволяют заменить запись вида: (Поле1, Поле1) В (ВЫБРАТЬ Поле1, Поле2 ИЗ Таблица) Если такое условие нужно использовать в условии виртуальной таблицы, то для этого нужно использовать оператор УсловиеВхождения.

Разберем пример замены следующего выражения:

(Номенклатура, МестоХранения) В 
    (ВЫБРАТЬ РАЗЛИЧНЫЕ 
        ВТ_ИЗМЕРЕНИЯ.Номенклатура, ВТ_ИЗМЕРЕНИЯ.МестоХранения 
    ИЗ 
        ВТ_ИЗМЕРЕНИЯ КАК ВТ_ИЗМЕРЕНИЯ)

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

Код 1С. Условие вхождения для виртуальной таблицы

//@Компайлер ТекстЗапросаВМодельЗапроса
//МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
;// ЗАПРОС ПАКЕТА. ВТ_ИЗМЕРЕНИЯ
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ИЗМЕРЕНИЯ")
    .Выбрать()
        .Поле("&Номенклатура", "Номенклатура")
        .Поле("&Склад", "МестоХранения")
;// ЗАПРОС ПАКЕТА. _ДемоОстаткиТоваровВМестахХраненияОстатки
МодельЗапроса.ЗапросПакета("_ДемоОстаткиТоваровВМестахХраненияОстатки")
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.Остатки")
            .УсловиеВхождения("ВТ_ИЗМЕРЕНИЯ")
        // Измерения
        .Поле("Номенклатура")
        .Поле("МестоХранения")
        .Поле("Организация")
        // Ресурсы
        .Поле("КоличествоОстаток")
    .Автопорядок()
;// Установка параметров
//МодельЗапроса
//    .Параметр("Номенклатура", )// 
//    .Параметр("Склад", )// 
;// Обработка результата
//МодельЗапроса.ВыполнитьЗапрос();
//Результат = МодельЗапроса.Результат("_ДемоОстаткиТоваровВМестахХраненияОстатки");

Запрос 1С. Результат применения условия вхождения

ВЫБРАТЬ
    &Номенклатура КАК Номенклатура,
    &Склад КАК МестоХранения
ПОМЕСТИТЬ ВТ_ИЗМЕРЕНИЯ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    _ДемоОстаткиТоваровВМестахХраненияОстатки.Номенклатура КАК Номенклатура,
    _ДемоОстаткиТоваровВМестахХраненияОстатки.МестоХранения КАК МестоХранения,
    _ДемоОстаткиТоваровВМестахХраненияОстатки.Организация КАК Организация,
    _ДемоОстаткиТоваровВМестахХраненияОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
    РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.Остатки(, (Номенклатура, МестоХранения) В (ВЫБРАТЬ РАЗЛИЧНЫЕ ВТ_ИЗМЕРЕНИЯ.Номенклатура, ВТ_ИЗМЕРЕНИЯ.МестоХранения ИЗ ВТ_ИЗМЕРЕНИЯ КАК ВТ_ИЗМЕРЕНИЯ)) КАК _ДемоОстаткиТоваровВМестахХраненияОстатки
АВТОУПОРЯДОЧИВАНИЕ

ОтборВхождения

Заменяет выражение вида

ГДЕ
    _ДемоНоменклатура.Ссылка В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                ВТ_ТАБЛИЦА.Номенклатура
            ИЗ
                ВТ_ТАБЛИЦА КАК ВТ_ТАБЛИЦА)

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

Код 1С. Пример модели с ОтборВхождения

//@Компайлер ТекстЗапросаВМодельЗапроса
//МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
;// ЗАПРОС ПАКЕТА. ВТ_ТАБЛИЦА
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ТАБЛИЦА")
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОборотыПоСчетамНаОплату.Обороты", "_ДемоОборотыПоСчетамНаОплатуОбороты")
        .Поле("_ДемоОборотыПоСчетамНаОплатуОбороты.Номенклатура")
        .Поле("_ДемоОборотыПоСчетамНаОплатуОбороты.СуммаОборот")
;// ЗАПРОС ПАКЕТА. 
МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОборотыПоСчетамНаОплату")
        .Источник("Справочник._ДемоНоменклатура")
        .ЛевоеСоединение("_ДемоОборотыПоСчетамНаОплату", "_ДемоНоменклатура")
            .Связь("Номенклатура = Ссылка")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Период")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Регистратор")
        .Поле("_ДемоОборотыПоСчетамНаОплату.НомерСтроки")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Активность")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Номенклатура")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Сумма")
        .Поле("_ДемоОборотыПоСчетамНаОплату.МоментВремени")
        .ОтборВхождения("ВТ_ТАБЛИЦА", "_ДемоНоменклатура.Ссылка = Номенклатура")

;// Обработка результата
//МодельЗапроса.ВыполнитьЗапрос();
//Результат = МодельЗапроса.Результат("ВТ_ТАБЛИЦА");

Код 1С. Результирующий запрос ОтборВхождения

ВЫБРАТЬ
    _ДемоОборотыПоСчетамНаОплатуОбороты.Номенклатура КАК Номенклатура,
    _ДемоОборотыПоСчетамНаОплатуОбороты.СуммаОборот КАК СуммаОборот
ПОМЕСТИТЬ ВТ_ТАБЛИЦА
ИЗ
    РегистрНакопления._ДемоОборотыПоСчетамНаОплату.Обороты КАК _ДемоОборотыПоСчетамНаОплатуОбороты
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    _ДемоОборотыПоСчетамНаОплату.Период КАК Период,
    _ДемоОборотыПоСчетамНаОплату.Регистратор КАК Регистратор,
    _ДемоОборотыПоСчетамНаОплату.НомерСтроки КАК НомерСтроки,
    _ДемоОборотыПоСчетамНаОплату.Активность КАК Активность,
    _ДемоОборотыПоСчетамНаОплату.Номенклатура КАК Номенклатура,
    _ДемоОборотыПоСчетамНаОплату.Сумма КАК Сумма,
    _ДемоОборотыПоСчетамНаОплату.МоментВремени КАК МоментВремени
ИЗ
    РегистрНакопления._ДемоОборотыПоСчетамНаОплату КАК _ДемоОборотыПоСчетамНаОплату
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник._ДемоНоменклатура КАК _ДемоНоменклатура
        ПО _ДемоОборотыПоСчетамНаОплату.Номенклатура = _ДемоНоменклатура.Ссылка
            И (_ДемоОборотыПоСчетамНаОплату.Номенклатура = _ДемоНоменклатура.Ссылка)
ГДЕ
    _ДемоНоменклатура.Ссылка В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                ВТ_ТАБЛИЦА.Номенклатура
            ИЗ
                ВТ_ТАБЛИЦА КАК ВТ_ТАБЛИЦА)

Связи в соединении

Когда в операторе соединения просто сопоставляются поля, их можно перечислить через запятую:

… ПО (Таблица1.ПолеA = Таблица2.ПолеA И Таблица1.ПолеB = Таблица2.ПолеB

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

… ПО (Таблица1.ПолеX) = (Таблица2.ПолеX) → … ПО ПолеX

Таким образом, при "чистом" совпадении имён полей запись упрощается: достаточно перечислить лишь уникальные имена полей.

Код 1С. Пример соединения через Связь

//@Компайлер ТекстЗапросаВМодельЗапроса
//МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
;// ЗАПРОС ПАКЕТА. 
МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОборотыПоСчетамНаОплату")
        .Источник("Справочник._ДемоНоменклатура")
        .Источник("Документ._ДемоСчетНаОплатуПокупателю")
        .ЛевоеСоединение("_ДемоОборотыПоСчетамНаОплату", "_ДемоСчетНаОплатуПокупателю")
            .Связь("Регистратор = Ссылка")
        .ЛевоеСоединение("_ДемоОборотыПоСчетамНаОплату", "_ДемоНоменклатура")
            .Связь("Номенклатура = Ссылка")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Период")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Регистратор")
        .Поле("_ДемоОборотыПоСчетамНаОплату.НомерСтроки")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Активность")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Номенклатура")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Сумма")
        .Поле("_ДемоОборотыПоСчетамНаОплату.МоментВремени")
;// Обработка результата
//МодельЗапроса.ВыполнитьЗапрос();

Код 1С. Пример совпадения полей в соединении

//@Компайлер ТекстЗапросаВМодельЗапроса
//МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
МодельЗапроса = Общий.МодельЗапроса()
;//  ЗАПРОС ПАКЕТА. ВТ_СТОРОНЫ_ДОГОВОРА
МодельЗапроса.ЗапросПакета().Поместить("ВТ_СТОРОНЫ_ДОГОВОРА")
    .Выбрать()
        .Источник("Справочник._ДемоКонтрагенты")
        .Источник("Справочник._ДемоДоговорыКонтрагентов")
        .ЛевоеСоединение("_ДемоКонтрагенты", "_ДемоДоговорыКонтрагентов")
            .Связь("Ссылка = Владелец")
        .Поле("_ДемоКонтрагенты.Ссылка", "Контрагент")
        .Поле("_ДемоДоговорыКонтрагентов.Ссылка", "Договор")
;//  ЗАПРОС ПАКЕТА.
МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Источник("ВТ_СТОРОНЫ_ДОГОВОРА")
        .Источник("Документ._ДемоЗаказПокупателя")
        .ЛевоеСоединение("ВТ_СТОРОНЫ_ДОГОВОРА", "_ДемоЗаказПокупателя")
            .Связь("Контрагент, Договор")
        .Поле("ВТ_СТОРОНЫ_ДОГОВОРА.*")
        .Поле("_ДемоЗаказПокупателя.Ссылка", "Заказ")
;

Функции языка запросов

Модель поддерживает специальные функции в виде полей:

  • ЕстьNull
  • Автономер
  • Представление
  • ПредставлениеСсылки
  • УИД
  • Подстрока
  • ДобавитьКДате

Код 1С. Пример использования функций языка запросов

//@Компайлер ТекстЗапросаВМодельЗапроса
//МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
;// ЗАПРОС ПАКЕТА. 
МодельЗапроса.ЗапросПакета().Поместить("ВТ")
    .Выбрать()
        .Источник("РегистрНакопления._ДемоОборотыПоСчетамНаОплату")
        .Источник("Справочник._ДемоНоменклатура")
        .Источник("Документ._ДемоСчетНаОплатуПокупателю")
        .ЛевоеСоединение("_ДемоОборотыПоСчетамНаОплату", "_ДемоСчетНаОплатуПокупателю")
            .Связь("Регистратор = Ссылка")
        .ЛевоеСоединение("_ДемоОборотыПоСчетамНаОплату", "_ДемоНоменклатура")
            .Связь("Номенклатура = Ссылка")
        .Поле("_ДемоОборотыПоСчетамНаОплату.Период")
        .УИД("_ДемоОборотыПоСчетамНаОплату.Регистратор")
        .ПредставлениеСсылки("_ДемоОборотыПоСчетамНаОплату.Регистратор")
        .Автономер("Код")
;// Обработка результата
//МодельЗапроса.ВыполнитьЗапрос();

Запрос 1С. Результат использования специальных полей

ВЫБРАТЬ
    _ДемоОборотыПоСчетамНаОплату.Период КАК Период,
    УНИКАЛЬНЫЙИДЕНТИФИКАТОР(_ДемоОборотыПоСчетамНаОплату.Регистратор) КАК Регистратор,
    ПРЕДСТАВЛЕНИЕССЫЛКИ(_ДемоОборотыПоСчетамНаОплату.Регистратор) КАК РегистраторПредставление,
    АВТОНОМЕРЗАПИСИ() КАК Код
ПОМЕСТИТЬ ВТ
ИЗ
    РегистрНакопления._ДемоОборотыПоСчетамНаОплату КАК _ДемоОборотыПоСчетамНаОплату
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник._ДемоНоменклатура КАК _ДемоНоменклатура
        ПО _ДемоОборотыПоСчетамНаОплату.Номенклатура = _ДемоНоменклатура.Ссылка
            И (_ДемоОборотыПоСчетамНаОплату.Номенклатура = _ДемоНоменклатура.Ссылка)
        ЛЕВОЕ СОЕДИНЕНИЕ Документ._ДемоСчетНаОплатуПокупателю КАК _ДемоСчетНаОплатуПокупателю
        ПО _ДемоОборотыПоСчетамНаОплату.Регистратор = _ДемоСчетНаОплатуПокупателю.Ссылка
            И (_ДемоОборотыПоСчетамНаОплату.Регистратор = _ДемоСчетНаОплатуПокупателю.Ссылка)

Параметры по месту использования

Одной из возможностей последней версии модели запроса является использование параметров запроса прямо в методах построения схемы. Например, раньше для чтения поля из параметра необходимо было указать имя параметра в поле &Параметр, а само значение задать в параметрах запроса. Теперь значение параметра можно передать в поле непосредственно при описании этого поля по месту.

Код 1С. Использование параметра запроса

МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Поле("&Период", "Период")
;

Код 1С. Непосредственное указание значения поля в методе строителя по месту

МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .Поле(ТекущаяДата(), "Период")
;

Параметры виртуальных таблиц также можно задать, используя переменные контекста выполнения. Это позволяет, например, указать в качестве значения для параметра периода текущую дату, а для видов субконто — перечислить значения коллекции элементов, последовательно передав ссылки на соответствующие планы видов характеристик.

Код 1С. Параметры виртуальной таблицы

;// ЗАПРОС ПАКЕТА. _ДемоЖурналПроводокБухгалтерскогоУчетаОбороты
МодельЗапроса.ЗапросПакета("_ДемоЖурналПроводокБухгалтерскогоУчетаОбороты")
    .Выбрать()
        .Источник("РегистрБухгалтерии._ДемоЖурналПроводокБухгалтерскогоУчета.Обороты", "_ДемоЖурналПроводокБухгалтерскогоУчетаОбороты")
            .НачалоПериода(НачалоДня(ТекущаяДата()))
            .Субконто(ПланыВидовХарактеристик._ДемоВидыСубконто.Контрагенты)
            .Субконто(ПланыВидовХарактеристик._ДемоВидыСубконто.Договоры)
        .Поле("Счет")
        .Поле("Субконто1")
        .Поле("Субконто2")

Выборка данных из объекта

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

  • ТаблицаЗначений
  • КоллекцияДанныхФормы
  • ТабличнаяЧасть
  • Строка, Структура - данные в формате JSON (в виде строки или структуры)
  • ТабличныйДокумент

Код 1С. Пример чтения из таблицы JSON

Таблица = "{
|    'Колонки': {'Объект': 'СТРОКА(50)', 'Статья': 'СТРОКА(50)', 'Сумма': 'ЧИСЛО(15, 2)'},
|    'Строки': [
|        ['Ор3', 'Ко8', 8.35],
|        ['Ор2', 'Ко4', 5.81],
|        ['Ор6', 'Ко7', 2.00],
|    ]
|}";

МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ТАБЛИЦА")
    .Источник(Таблица) // таблица JSON
    .Поле("*")
;
МодельЗапроса.ЗапросПакета()
    .Источник("ВТ_ТАБЛИЦА")
    .Поле("*")
;
Результат = МодельЗапроса.ВыполнитьЗапрос().Результат().Выгрузить();

Таким же образом можно выбрать данные из табличного документа.

Таблица в табличном документе

Таблица в табличном документе

Код 1С. Выбор данных из табличного документа

Таблица = Новый ТабличныйДокумент();
Таблица.Прочитать("Таблица.mxl");

МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ТАБЛИЦА")
    .Источник(Таблица) // табличный документ
    .Поле("*")
;
МодельЗапроса.ЗапросПакета()
    .Источник("ВТ_ТАБЛИЦА")
    .Поле("*")
;
Результат = МодельЗапроса.ВыполнитьЗапрос().Результат().Выгрузить();

Представления


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

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

Ниже приведены примеры реализованных представлений:

  • ПредставлениеСрезДат - получение таблицы дат для указанного диапазона;
  • ПредставлениеСрезПоследнихПоДатам - выборка последних записей в разрезе дат;
  • ПредставлениеОборотыИОстаткиПоДатам - расчёт оборотов и остатков на заданные даты.

ПредставлениеСрезДат

Представление ПредставлениеСрезДат по сути заменяет объединение 4-х подзапросов. Поскольку это объединение, то использовать его результат по месту не получится, необходимо поместить результат во временную таблицу. В коде ниже объявляется источник ПредставлениеСрезДат с непосредственным указанием параметров из переменных окружения. Поля запроса описывать не нужно, т.к. они уже предопределены в представлении. Для данного представления определено одно поле Дата. Далее результат помещается во временную таблицу ВТ_ДАТЫ (это имя выбрано для примера, можно указать любое другое).

Пример получения диапазона дат взят из Инструменты разработчика

Код 1С. ПредставлениеСрезДат с непосредственной передачей параметров из окружения

//@Компайлер ТекстЗапросаВМодельЗапроса
МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
ДатаНачала = НачалоМесяца(ТекущаяДата());
ДатаОкончания = КонецМесяца(ТекущаяДата());
;// ЗАПРОС ПАКЕТА. ВТ_ДАТЫ
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ДАТЫ")
    .ПредставлениеСрезДат(ДатаНачала, ДатаОкончания)
;// Обработка результата

Код ниже аналогичен предыдущему примеру. Отличие здесь в том, что в качестве параметров Представления передаются значения параметров запроса.

Код 1С. ПредставлениеСрезДат с параметризацией

//@Компайлер ТекстЗапросаВМодельЗапроса
МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
ДатаНачала = НачалоМесяца(ТекущаяДата());
ДатаОкончания = КонецМесяца(ТекущаяДата());
;// ЗАПРОС ПАКЕТА. ВТ_ДАТЫ
МодельЗапроса.ЗапросПакета().Поместить("ВТ_ДАТЫ")
    .ПредставлениеСрезДат("&ДатаНачала", "&ДатаОкончания")
;// Установка параметров
МодельЗапроса
    .Параметр("ДатаНачала", ДатаНачала)// Дата
    .Параметр("ДатаОкончания", ДатаОкончания)// Дата
;// Обработка результата

Запрос 1С. ПредставлениеСрезДат

ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2026, 3, 1, 0, 0, 0), ДЕНЬ, aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a) КАК Дата
ПОМЕСТИТЬ ВТ_ДАТЫ
ИЗ
    (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК aa,
    (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК bb,
    (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК cc,
    (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК dd
ГДЕ
    aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a <= РАЗНОСТЬДАТ(ДАТАВРЕМЯ(2026, 3, 1, 0, 0, 0), ДАТАВРЕМЯ(2026, 3, 31, 23, 59, 59), ДЕНЬ)

ПредставлениеСрезПоследнихПоДатам

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

Код 1С. ПредставлениеСрезПоследнихПоДатам

//@Компайлер ТекстЗапросаВМодельЗапроса
МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса();
ДатаНачала = НачалоМесяца(ТекущаяДата());
ДатаОкончания = КонецМесяца(ТекущаяДата());
;// ЗАПРОС ПАКЕТА. _ДемоРаботникиОрганизаций
МодельЗапроса.ЗапросПакета()
    .Выбрать()
        .ПредставлениеСрезПоследнихПоДатам("РегистрСведений._ДемоРаботникиОрганизаций", "&ДатаНачала", "&ДатаОкончания")
    .Порядок("Дата")
    .Порядок("Организация")
    .Автопорядок()
;// Установка параметров
МодельЗапроса
    .Параметр("ДатаНачала", ДатаОкончания - 3600*24*5)// Дата
    .Параметр("ДатаОкончания", ДатаОкончания)// Дата
;// Обработка результата

Запрос 1С. ПредставлениеСрезПоследнихПоДатам

ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a) КАК Дата
ПОМЕСТИТЬ _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8
ИЗ
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК aa,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК bb,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК cc,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК dd
ГДЕ
    aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a <= РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8.Дата КАК Дата,
    МАКСИМУМ(_ДемоРаботникиОрганизаций.Период) КАК Период
ПОМЕСТИТЬ _ДемоРаботникиОрганизаций_ПЕРИОДЫ
ИЗ
    _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8 КАК _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений._ДемоРаботникиОрганизаций КАК _ДемоРаботникиОрганизаций
        ПО (_cd5ed437_83d2_46ad_89d9_1a772c1e6fc8.Дата >= _ДемоРаботникиОрганизаций.Период)
ГДЕ
    _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания

СГРУППИРОВАТЬ ПО
    _cd5ed437_83d2_46ad_89d9_1a772c1e6fc8.Дата
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    _ДемоРаботникиОрганизаций_ПЕРИОДЫ.Дата КАК Дата,
    _ДемоРаботникиОрганизаций.Период КАК Период,
    _ДемоРаботникиОрганизаций.Организация КАК Организация,
    _ДемоРаботникиОрганизаций.ФизическоеЛицо КАК ФизическоеЛицо,
    _ДемоРаботникиОрганизаций.ПодразделениеОрганизации КАК ПодразделениеОрганизации,
    _ДемоРаботникиОрганизаций.ЗанимаемыхСтавок КАК ЗанимаемыхСтавок,
    _ДемоРаботникиОрганизаций.ТабельныйНомер КАК ТабельныйНомер
ИЗ
    _ДемоРаботникиОрганизаций_ПЕРИОДЫ КАК _ДемоРаботникиОрганизаций_ПЕРИОДЫ
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений._ДемоРаботникиОрганизаций КАК _ДемоРаботникиОрганизаций
        ПО (_ДемоРаботникиОрганизаций_ПЕРИОДЫ.Период = _ДемоРаботникиОрганизаций.Период)

УПОРЯДОЧИТЬ ПО
    Дата,
    Организация
АВТОУПОРЯДОЧИВАНИЕ

ПредставлениеОборотыИОстаткиПоДатам

Следующее представление аналогично предыдущему ПредставлениеСрезПоследнихПоДатам, но для виртуальной таблицы ОстаткиИОбороты.

Код 1С. ПредставлениеОборотыИОстаткиПоДатам

ДатаНачала = '20120101';
ДатаОкончания = '20140808';
МодельЗапроса.ЗапросПакета()
    .Выбрать() 
        .ПредставлениеОборотыИОстаткиПоДатам("РегистрНакопления._ДемоОстаткиТоваровВМестахХранения.ОстаткиИОбороты", 
            "&ДатаНачала", "&ДатаОкончания", 
            "Организация, МестоХранения, Номенклатура", 
            "Количество", 
            "Номенклатура = &Номенклатура И МестоХранения = &МестоХранения")
    .Порядок("Организация")
    .Порядок("Номенклатура")
    .Порядок("МестоХранения")
    .Порядок("Дата")
    .Автопорядок()
;// Установка параметров
МодельЗапроса
    .Параметр("ДатаНачала", ДатаНачала)// Дата
    .Параметр("ДатаОкончания", ДатаОкончания)// Дата
;// Обработка результата

Запрос 1С. ПредставлениеОборотыИОстаткиПоДатам

ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a) КАК Дата
ПОМЕСТИТЬ _58825567_5aff_46a6_b295_410f8f7e7b53
ИЗ
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК aa,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК bb,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК cc,
(ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9) КАК dd
ГДЕ
    aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a <= РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ)
;

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    _58825567_5aff_46a6_b295_410f8f7e7b53.Дата КАК Дата,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Организация КАК Организация,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.МестоХранения КАК МестоХранения,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Номенклатура КАК Номенклатура,
    МАКСИМУМ(_ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Период) КАК Период
ПОМЕСТИТЬ _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ПЕРИОДЫ
ИЗ
    _58825567_5aff_46a6_b295_410f8f7e7b53 КАК _58825567_5aff_46a6_b295_410f8f7e7b53
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ КАК _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ
        ПО (_58825567_5aff_46a6_b295_410f8f7e7b53.Дата >= _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Период)

СГРУППИРОВАТЬ ПО
    _58825567_5aff_46a6_b295_410f8f7e7b53.Дата,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Организация,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.МестоХранения,
    _ДемоОстаткиТоваровВМестахХраненияОстаткиИОбороты_ОСТАТКИ_И_ОБОРОТЫ.Номенклатура
;

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

УПОРЯДОЧИТЬ ПО
    Организация,
    Номенклатура,
    МестоХранения,
    Дата
АВТОУПОРЯДОЧИВАНИЕ

Область применения


Общий вывод я для себя сделал такой. Область применения схемы:

  • динамические запросы
  • точечные "инъекции" для изменения типовых запросов, если нет повышенных требований к производительности
  • моделирование сложных запросов в период разработки, а на прод помещать уже готовый текст запроса
  • для обучения по работе со схемой запроса
  • для применения алгоритмической сборки сложных запросов с регулярной структурой

Области применения

Области применения

Динамические запросы

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

Универсальный подход к построению запросов, находит применение в широком круге задач. Среди них - организация произвольных фильтров для отбора данных, перенос (конвертация) информации из одних структур в другие, а также подготовка данных в строго заданном формате.

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

Поддержка типовых решений

Объектное представление запроса появилось в платформе с версии 8.3.5 в 2014 году. Поддержка решений на базе типовых конфигураций требует внесение изменений в алгоритмы вендора. Текст запроса часто собирается из фрагментов текста. Используются вставки в текст специальных меток, чтобы затем заменить их на другой текст. Для динамических запросов используются вставки в запрос с проверкой значения переменной по условию ИЛИ, например так: ГДЕ &ЕстьФлаг ТОГДА УСЛОВИЕ ИЛИ ИСТИНА.

Многочисленные вставки в текст запроса усложняют дальнейшее понимание изменений и поддержку при обновлении конфигурации поставщика.

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

В следующем фрагменте кода производится модификация типового запроса. Модифицированные блоки находятся между комментариями вида // ++ и // --. Вот эти модификации:

  1. ВТТаблицаДокумента - новая временная таблица из объекта
  2. ИмяКолонки - новое поле, имя которого определяется в коде и заменяется в тексте запроса через СтрЗаменить
  3. Убрана группировка в запросе через комментирование секции СГРУППИРОВАТЬ ПО и замены агрегатных функций на имя поля
  4. В запросе пакета добавлено соединение с новой временной таблицей
  5. Добавлено условие, которое в исходном виде выглядит так: (НЕ &УдалятьНулевыеСчетаФактуры ИЛИ ВТ_УдаляемыеСчетаФактуры.СчетФактураДокумент ЕСТЬ NULL)
  6. Добавлено новое поле
  7. В последнем запросе добавлено новое поле

Код 1С. Вот так выглядят правки через использование модели запроса

    // ++ модификация типового запроса
    МодельЗапроса = РаботаСМодельюЗапроса.МодельЗапроса(Запрос);
    МодельЗапроса.ВставитьЗапросПакета(0).Поместить("ВТТаблицаДокумента")
        .Источник(ТаблицаДокумента) // выборка из объекта
        .Поле("*")
    ;
    МодельЗапроса.УстановитьЗапросПакета("ВТСгруппированнаяТаблицаДокумента")
        .Поле(ИмяКолонки) // новое поле
        .Поле("СуммаБезНДС", "СуммаБезНДС") // замещение поля "СУММА(СуммаБезНДС)"
        .Поле("НДС", "НДС") // замещение поля "СУММА(НДС)"
        .Поле("НДСВал", "НДСВал") // замещение поля "СУММА(НДСВал)"
        .ОчиститьГруппировки() // очистка группировки
    ;
    МодельЗапроса.УстановитьЗапросПакета("ТаблицаВосстановления")
        .Источник("ВТТаблицаДокумента")
            .ЛевоеСоединение("ВТСгруппированнаяТаблицаДокумента", "ВТТаблицаДокумента")
                .Связь("СтавкаНДС, ВидЦенности, СчетУчетаНДС")
        .УсловныйОтбор(УдалятьНулевыеСчетаФактуры, "ВТ_УдаляемыеСчетаФактуры.СчетФактураДокумент ЕСТЬ NULL")
        .Поле(ИмяКолонки)
    ;
    МодельЗапроса.УстановитьЗапросПакета() // позиция на последнем запросе
        .Поле(ИмяКолонки) // новое поле
    ;
    Запрос = МодельЗапроса.Запрос();
    // -- модификация типового запроса

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

Итого получается вместо множества точечных изменений правка производится в одном месте.

Быстрое моделирование и прототипирование

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

Благодаря поддержке шорткатов (сокращённых конструкций) и возможности чтения данных напрямую из объектов, процесс разработки существенно ускоряется: алгоритмы с использованием запросов можно буквально "набрасывать" в рабочем порядке, не отвлекаясь на формальные детали реализации.

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

Моделирование сложных запросов

Применение шорткатов (сокращенных конструкций) позволяет существенно упростить разработку запросов: УсловиеВхождения, Связь.

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

  • Период - блок, отвечающий за временну'ю привязку данных (например, период, дата, регистратор);
  • Измерения - набор ключевых аналитических разрезов, таких как организация, контрагент, договор;
  • Ресурсы - числовые или количественные показатели, которые агрегируются по заданным измерениям (сумма, количество, сумма НДС и т.п.);
  • Реквизиты - сопутствующие атрибуты, описывающие измерения (например, ИНН).

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

Код 1С. Измерения, ресурсы

    ;//  ЗАПРОС ПАКЕТА.
    МодельЗапроса.ЗапросПакета().Поместить("ВТ_ДАТЫ_ВЫПИСКИ")
        .Источник("ВТ_БАНКОВСКИЕ_СЧЕТА")
        .Источник("Документ.СообщениеОбменСБанками")
        .ВнутреннееСоединение("ВТ_БАНКОВСКИЕ_СЧЕТА", "СообщениеОбменСБанками")
            .Связь("НастройкаОбмена, НомерСчета")
            .УсловиеСвязи("%2.ДатаНачала <= %1.ДатаНачалаПоследнейЗагрузки")
            .УсловиеСвязи("%2.ДатаОкончания >= %1.ДатаКонцаПоследнейЗагрузки")
            .УсловиеСвязи("%2.ВидЭД = ЗНАЧЕНИЕ(Перечисление.ВидыЭДОбменСБанками.ВыпискаБанка)")
        //  Измерения
        .Поле("ВТ_БАНКОВСКИЕ_СЧЕТА.Ссылка", "БанковскийСчет")
        .Поле("ВТ_БАНКОВСКИЕ_СЧЕТА.НомерСчета")
        //  Ресурсы
        .Максимум("СообщениеОбменСБанками.Дата")
    ;//  ЗАПРОС ПАКЕТА.

Код 1С. Измерения, ресурсы, реквизиты

    ;//  ЗАПРОС ПАКЕТА. ВТ_ДАННЫЕ_РАЗМЕЩЕНИЯ
    МодельЗапроса.ЗапросПакета().Поместить("ВТ_ДАННЫЕ_РАЗМЕЩЕНИЯ")
        .Источник("Документ.РазмещениеЗаявкиВПлатежнойПозиции", "РазмещениеЗаявки")
        .Источник("Документ.ЗаявкаНаОперацию", "ЗаявкаНаОперацию")
        .ВнутреннееСоединение("РазмещениеЗаявки", "ЗаявкаНаОперацию")
            .Связь("ДокументПланирования = Ссылка")
        .Отбор("РазмещениеЗаявки.Ссылка = &ДокументРазмещения")
        //  Измерения
        .Поле("РазмещениеЗаявки.Организация")
        .Поле("РазмещениеЗаявки.ДокументПланирования")
        .Поле("РазмещениеЗаявки.Ссылка", "ДокументРазмещения")
        .Поле("ЗНАЧЕНИЕ(Перечисление.СостоянияИсполненияПозицииЗаявки.Размещена)", "СостояниеИсполнения")
        //  Ресурсы
        .Поле("РазмещениеЗаявки.СуммаВзаиморасчетов", "Сумма")
        //  Реквизиты
        .Поле("ЗаявкаНаОперацию.КоличествоПлатежныхПоручений")
        .Поле("ЗаявкаНаОперацию.ЕстьПакетПлатежныхДокументов")
        .Поле("РазмещениеЗаявки.ЕстьКонтрольЛимитовБанка")
        .Поле("РазмещениеЗаявки.ФормаОплаты")
    ;//  ЗАПРОС ПАКЕТА. ВТ_ДАННЫЕ_РАЗМЕЩЕНИЯ_ШАБЛОНОВ_КБ

Алгоритмическое построение запросов

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

Одним из способов укрощения этой сложности являются Представления. Это своеобразные шаблоны запросов, которые маскируют внутреннюю структуру, позволяя указывать их как источники по типу виртуальных таблиц. Если же нужного Представления нет для специфики задачи, а запрос все равно получается избыточным, можно применить алгоритмическую сборку.

Суть подхода заключается в том, чтобы перенести избыточность из плоскости запроса в плоскость алгоритмов и структур данных высокого уровня. Алгоритм собирает итоговый запрос как конструктор, уменьшая объем кода. Это делает код не только чище, но и более гибким.

Обучение по работе со схемой запроса

В эпоху ИИ кажется, что пришёл переломный момент: теперь не нужно «перелопачивать» тонны справочной литературы, чтобы вспомнить нужный метод или найти решение программной задачи. Однако не всё поддаётся искусственному интеллекту. Когда информации о конкретном инструменте мало, ИИ практически бессилен. Одной из таких «серых зон», поR09;видимому, является работа со схемой запроса.

Мой опыт общения с «Напарником» показал, что он путает схему запроса с СКД, часто выдумывает детали и в целом не знает темы. Тем не менее ситуация не безнадежна:

  1. Показать модуль РаботаСМодельюЗапроса.
    Если продемонстрировать Напарнику, как в этом модуле формируется схема, то он способен сгенерировать вполне рабочий код конструирования схемы.

  2. Самостоятельное изучение модуля.
    Наиболее надёжный способ – открыть модуль и изучить используемые приёмы. Это даёт глубокое понимание и позволяет адаптировать решения под свои задачи.

  3. Использовать Конструктор модели запроса.
    Дополнительный инструмент по работе с моделью запроса "Конструктор модели запроса" позволяет по тексту запроса и получить готовый код в одном из вариантов использования модулей:

    • РаботаСоСхемойЗапроса (классический стиль, близкий к исходному использованию схемы запроса)
    • РаботаСМодельюЗапроса (классический стиль)
    • МодельЗапроса (объектная модель)

    После генерации кода вы можете изучить его внутреннюю реализацию и перенять проверенные приёмы.

Таким образом, хотя ИИ пока не в состоянии полностью заменить человека в работе со схемой запроса, комбинация демонстрации готового модуля и использования Конструктора Модели Запроса позволяет быстро получить корректный и поддерживаемый код.

Производительность


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

Время работы любого кода зависят от процессора, количества ядер, объёма кеша и даже от того, какой ОСR09;драйвер обслуживает запросы к диску. Поэтому абсолютные цифры здесь полезны лишь как относительный ориентир: они показывают, насколько одна реализация быстрее другой при одинаковых условиях.

По моим замерам текстовый способ построения запроса - это примерно десятки микросекунд. Работа со схемой запроса - это уже миллисекунды. Получается указание прямого текста запроса - это экономия до 2-х порядков времени исполнения.

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

Таблица. Сравнение производительности подходов генерации текста запроса по схеме запроса

Библиотека Кратко о реализации Особенности Потери (по сравнению с самым быстрым)
1. РаботаСоСхемойЗапроса нативные функции, напрямую работают со схемой без дополнительного уровня абстракции Самый «чистый» код, минимум оверхеда 0% (самый быстрый)
2. МодельЗапроса_2 Объектная обёртка над тем же нативным API, но использует ООП слой Добавлены удобные методы, шорткаты +5%
3. РаботаСМодельюЗапроса нативные функции, напрямую работают со схемой без дополнительного уровня абстракции Идентична алгоритмически МодельЗапроса_2, однако каждое обращение через точку создаёт небольшие накладные расходы +7%
4. МодельЗапроса_1_2 Объектная реализация, основанная на другой (устаревшей) библиотеке РаботаСоСхемойЗапроса Поддерживает полный набор функций МодельЗапроса_2, но вызовы проходят через дополнительный слой библиотеки-посредника +10%

Пъедистал производительности

Пъедистал производительности

Конструктор модели запроса


Разработка кода с использованием операторов модели запроса представляет собой нетривиальную задачу. Сложность здесь заключается не столько в отсутствии контекстной подсказки (которая, справедливости ради, для методов всё же существует), сколько в том, что применение функций модели подчиняется строгой синтаксической последовательности, которую среда разработки на текущий момент не в состоянии полноценно контролировать.

Наиболее эффективным инструментом при написании и отладке модели выступает Конструктор модели запроса. Данное средство обеспечивает двунаправленную трансформацию: по тексту запроса генерируется код модели, а из кода модели восстанавливается текст запроса.

Ключевым новшеством в актуальной версии конструктора стало применение технологии Компайлеров - специализированных обработок, объединённых единым интерфейсом и отвечающих за перевод текста запроса в программный код модели и обратно. В настоящее время доступны Компайлеры:

  • ТекстЗапросаВРаботуСоСхемойЗапроса
  • ТекстЗапросаВРаботуСМодельюЗапроса
  • ТекстЗапросаВМодельЗапроса

Подобный архитектурный подход позволил унифицированным образом поддерживать различные методы генерации кода.

Конструктор модели запроса

Конструктор модели запроса

Состав и установка


Состав

  • общий модули библиотеки РаботаСоСхемойЗапроса, РаботаСМодельюЗапроса
  • обработка МодельЗапроса, реализующая объектный интерфейс
  • вспомогательные обработки, реализующие перевод текста запроса в модель для использования в конструкторе: КомпайлерРаботаСоСхемойЗапроса, КомпайлерРаботаСМодельюЗапроса, КомпайлерМодельЗапроса
  • обработка КонструкторМоделиЗапроса

Установка

Объединить с файлом конфигурации из Демо-базы:

Второй способ - собрать свою конфигурацию из подсистем с github (ссылки указаны в подсистемах). На github доступны сборки как в cf, так и cfe. Во втором случае можно просто установить расширения подсистем без необходимости вносить изменения в конфигурацию.

Зависимости

Проект разрабатывается на EDT и выложен в общий доступ на github. Текущая версия платформы 1С 8.3.27.


Проверено на следующих конфигурациях и релизах:

  • 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.10.256

Вступайте в нашу телеграмм-группу Инфостарт

Схема запроса текст запроса запрос модель запроса представления

См. также

Инструментарий разработчика Чистка данных Свертка базы Инструменты администратора БД Системный администратор Программист Руководитель проекта 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP, УНФ, КА и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы. Может выполнять свертку одновременно в несколько потоков. А так же автоматически, без непосредственного участия пользователя. Решение в Реестре отечественного ПО

24900 руб.

20.08.2024    63140    277    160    

297

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    250504    1389    421    

1143

Пакетная печать Печатные формы Инструментарий разработчика Программист 1С:Предприятие 8 Платные (руб)

Расширение для создания и редактирования печатных форм в системе 1С:Предприятие 8.3. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и прозрачность разработки, а также навести порядок в многообразии корпоративных печатных форм.

22570 руб.

06.10.2023    36422    97    40    

115

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданым 1С, справке синтакс-помошника и проверки синтаксиса.

15250 руб.

25.08.2025    47350    98    27    

111

Инструменты администратора БД Инструментарий разработчика Роли и права Программист 1С:Предприятие 8 1C:Бухгалтерия Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

17000 руб.

10.11.2023    24237    91    42    

101

Инструментарий разработчика Программист 1С:Предприятие 8 Платные (руб)

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

9500 руб.

17.05.2024    50990    181    63    

209

SALE! %

Мастера заполнения Поиск данных Инструментарий разработчика Подбор и обработка объектов 1С 8.3 1С 8.5 Платные (руб)

Infostart MagicInput улучшает подбор в полях ввода 1С: ищет по любой части названия и по нескольким ключевым фрагментам, распознаёт ввод в другой раскладке и показывает иконки/статусы объектов прямо в списке. Поддерживает вставку навигационной ссылки/представления документа для автоподбора; для разработчиков доступны поиск по GUID и полному имени предопределённого. Работает в управляемых формах и подключается в большинстве конфигураций 1С 8.3/8.5.

5000 4000 руб.

25.02.2026    2366    11    1    

11
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. provadyuga 112 29.03.26 13:16 Сейчас в теме
Не очень понятно из описания, что собственно делает в итоге эта разработка. Это планировщик запроса что ли или оптимизатор? Область применения какая?
3. kalyaka 1151 29.03.26 17:10 Сейчас в теме
(1) Спасибо за вопрос! Я уже достаточно долго использую эту библиотеку и при написании статьи просто забыл про обязательную вводную часть.

Исправил, добавил вводную часть в начало статьи "От текста запроса к объектной модели". Если кратко, то это расширение платформенного объекта "Схема запроса". Ее назначение - свернуть контекст, необходимый для манипуляций со структурой запроса через объект схемы запроса.

Область применения раскрыта в разделе "Область применения".
2. dhurricane 29.03.26 14:48 Сейчас в теме
А дать возможность писать собственные представления планируется? На сколько это будет трудоемкая задача без знаний "кишок" Вашей подсистемы, и возможно ли это вообще?
4. kalyaka 1151 29.03.26 17:38 Сейчас в теме
(2) Да, можно писать собственные представления, а уже реализованные использовать как образец.

При проектировании поддержки представлений я исходил из того, что они должны строиться на базе той же модели запроса. Это значит, что для добавления собственных представлений необходимо только разбираться как работать с самой моделью. Для этого должно быть достаточно освоить базовые принципы работы с моделью запроса. Еще должен помочь "Конструктор модели запроса" с возможностью двунаправленной работы из текста запроса в модель и обратно.
5. dhurricane 29.03.26 20:18 Сейчас в теме
(4) Правильно ли я понял из примеров, что Представление должно быть сконфигурировано сразу и за счет передаваемых в метод представления параметров функции? Т.е. у меня не получится задавать какие-то параметры представления методом `МодельЗапроса.ПараметрТаблицы`, например? Или в зависимости от того, какие поля перечислены вызовами `МодельЗапроса.Поле`, те поля в представлении и рассчитать, не объявляя их предварительно в аргументах создания представления?
6. kalyaka 1151 29.03.26 21:35 Сейчас в теме
(5) Да, верно. Метод ПараметрыТаблицы относится только к параметрам виртуальной таблицы.

Пока так, а в принципе, конечно, хотелось бы скопировать подход как к виртуальным таблицам. И вообще, можно было бы просто обращаться к Представлению по имени, например так: Источник("Представление.СрезДат"), но это мысли на будущие реализации :)
Для отправки сообщения требуется регистрация/авторизация