Как программно установить ограничение количества записей (ВЫБРАТЬ ПЕРВЫЕ) через Схему Запроса в 1С?

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

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

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

Базовый механизм реализации через Схему Запроса

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

Проанализируем пример кода, который решает эту задачу:


// 1. Создаем объект Запрос и задаем исходный текст
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |	РасхожденияПриПересчете.Номенклатура КАК Номенклатура,
               |	РасхожденияПриПересчете.Дата КАК Дата,
               |	РасхожденияПриПересчете.Пересчет КАК Пересчет
               |ИЗ
               |	РегистрСведений.РасхожденияПриПересчете КАК РасхожденияПриПересчете
               |ГДЕ
               |	РасхожденияПриПересчете.Расхождение = 0";

// 2. Инициализируем СхемуЗапроса и загружаем в нее текст
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);

// 3. Выбираем первый пакет запроса (если запрос не пакетный, он всегда будет под индексом 0)
ЗапросВыбора = СхемаЗапроса.ПакетЗапросов[0];

// 4. Обращаемся к первому оператору (выборке) в этом запросе
ОператорВыбрать = ЗапросВыбора.Операторы[0];

// 5. Устанавливаем ограничение количества записей (аналог ВЫБРАТЬ ПЕРВЫЕ 10)
ОператорВыбрать.КоличествоПолучаемыхЗаписей = 10;

// 6. Получаем модифицированный текст запроса обратно
Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();

Как мы видим из примера, свойство КоличествоПолучаемыхЗаписей принадлежит не самому объекту СхемаЗапроса, а конкретному оператору в пакете. Это дает гибкость, но требует понимания структуры коллекции Операторы.

Работа с объединениями (ОБЪЕДИНИТЬ)

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

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

Взаимодействие с уникальностью записей

Рассмотрим ситуацию, когда необходимо не просто выбрать первые записи, но и обеспечить их уникальность (аналог ВЫБРАТЬ РАЗЛИЧНЫЕ). В СхемеЗапроса за это отвечает свойство ВыбиратьРазличные.

Проанализируем порядок выполнения: платформа сначала определяет уникальные строки согласно логике ВыбиратьРазличные = Истина, и только после этого применяет ограничение, заданное в КоличествоПолучаемыхЗаписей. Это критично для оптимизации работы с большими таблицами, где нужно получить, например, список 10 последних уникальных цен номенклатуры.

Обязательность программной сортировки

Разберем одну из самых частых ошибок. Использование ВЫБРАТЬ ПЕРВЫЕ без явной сортировки делает результат запроса недетерминированным. СУБД вернет записи в том порядке, в котором ей удобнее их прочитать с диска в данный момент.

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


// Допустим, мы хотим сортировать по дате (второе поле в нашей выборке)
ПолеДата = ЗапросВыбора.Колонки[1].Поле; // Получаем поле Дата
ЗапросВыбора.Порядок.Добавить(ПолеДата);

Только при наличии четко заданного порядка использование лимита записей становится корректным с точки зрения бизнес-логики.

Ограничения параметров и динамика

Важно помнить, что в отличие от стандартного SQL, где в TOP иногда можно передать переменную, механизм запросов 1С требует, чтобы значение ВЫБРАТЬ ПЕРВЫЕ было жестко прописано в тексте как целое число. Следовательно, в свойство КоличествоПолучаемыхЗаписей нельзя передать имя параметра (например, &Лимит).

Если вам нужно, чтобы пользователь сам выбирал, сколько записей выводить (10, 50 или 100), вам придется каждый раз модифицировать СхемуЗапроса и генерировать новый текст запроса перед его выполнением. Схема запроса идеально подходит для этой задачи, так как она делает такую подстановку безопасной и структурной.

Пакетные запросы и временные таблицы

Если вы работаете с временными таблицами, структура СхемаЗапроса.ПакетЗапросов становится еще более полезной. Каждый элемент этой коллекции может быть либо объектом типа ЗапросВыбора, либо ЗапросВыбораВоВременнуюТаблицу.

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

Как сбросить ограничение

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

Проанализируем это действие:


// Сброс лимита для получения всех записей
ОператорВыбрать.КоличествоПолучаемыхЗаписей = 0;
// Теперь ПолучитьТекстЗапроса() вернет текст без конструкции ПЕРВЫЕ

Это делает СхемуЗапроса мощным инструментом для создания универсальных динамических фильтров в сложных программных модулях 1С.

← На главную