К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как сформировать запрос в 1С: пошаговое руководство

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

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

Язык запросов 1С похож на SQL, но адаптирован под структуру конфигурации: вместо таблиц базы данных используются объекты метаданных — справочники, документы, регистры накопления и сведений. Составить запрос можно двумя способами: визуально через конструктор запроса или вручную, написав текст запроса в модуле. Оба подхода дают одинаковый результат, разница только в скорости разработки и контроле над деталями.

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

Как сформировать запрос через конструктор

Конструктор запроса — встроенный визуальный инструмент конфигуратора. Он открывается из любого модуля: правый клик в тексте модуля → «Конструктор запроса». Если курсор стоит внутри строки с текстом запроса, конструктор загрузит существующий запрос для редактирования; если в пустом месте — предложит создать новый.

Работа в конструкторе строится по вкладкам. На вкладке «Таблицы и поля» в левой части выбирается объект метаданных (например, регистр накопления «ТоварыНаСкладах»), он переносится в список таблиц, после чего из таблицы выбираются нужные поля. На вкладке «Связи» настраиваются соединения нескольких таблиц, на вкладке «Условия» — отборы, на вкладке «Группировка» — итоги и агрегатные функции. Вкладка «Итоги» отвечает за итоговые записи по группам.

Порядок действий в конструкторе
  1. 1
    Откройте модуль и вызовите конструктор запроса через контекстное меню
  2. 2
    На вкладке «Таблицы и поля» выберите нужный справочник, документ или регистр
  3. 3
    Перенесите требуемые поля в список выбранных полей
  4. 4
    Задайте условия отбора на вкладке «Условия», используя параметры (&Параметр)
  5. 5
    При необходимости настройте группировку и итоги
  6. 6
    Нажмите «ОК» — конструктор сформирует текст запроса и заготовку кода

После нажатия «ОК» конструктор вставит в модуль не только текст запроса, но и шаблон кода: создание объекта Запрос, присвоение текста, выполнение и обход выборки. Это удобная отправная точка, но код почти всегда требует доработки — передачи параметров и обработки результата под конкретную задачу.

Базовый синтаксис языка запросов 1С

Минимальный запрос состоит из двух обязательных секций: ВЫБРАТЬ (какие поля нужны) и ИЗ (откуда их брать). Таблицы указываются через точку по типу объекта: Справочник.Номенклатура, Документ.РеализацияТоваров, РегистрНакопления.Продажи. Регистры сведений обозначаются как РегистрСведений.ИмяРегистра.

Дополнительные секции расширяют выборку: ГДЕ — отбор строк по условию, УПОРЯДОЧИТЬ ПО — сортировка, СГРУППИРОВАТЬ ПО — группировка с агрегатными функциями СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. Ключевое слово РАЗЛИЧНЫЕ убирает дубли строк, а ПЕРВЫЕ N ограничивает количество возвращаемых записей.

bsl
ВЫБРАТЬ
	Товары.Ссылка КАК Номенклатура,
	Товары.Наименование КАК Наименование
ИЗ
	Справочник.Номенклатура КАК Товары
ГДЕ
	Товары.ЭтоГруппа = ЛОЖЬ
	И Товары.ПометкаУдаления = ЛОЖЬ
УПОРЯДОЧИТЬ ПО
	Товары.Наименование

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

Как выполнить запрос программно и передать параметры

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

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

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
	// обработка строки: Выборка.Номенклатура, Выборка.Количество
КонецЦикла;

Параметры в тексте запроса обозначаются символом «&» и обязательно должны быть установлены до вызова Выполнить() — иначе платформа выдаст ошибку «Параметр не установлен». В параметры можно передавать примитивные значения, ссылки, даты, массивы и списки значений. Массивы особенно полезны для условий вида «Поле В (&СписокЗначений)».

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

Маршрут решения

Как выбрать способ получения результата

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

Условия, соединения и группировки

Условия в секции ГДЕ поддерживают сравнения, логические И/ИЛИ, проверку на NULL (ЕСТЬ NULL / НЕ ЕСТЬ NULL), вхождение в список (В), подобие строки (ПОДОБНО с шаблоном «%текст%») и вхождение в иерархию (В ИЕРАРХИИ). Для строковых полей сравнение через «=» требует точного совпадения с учётом дополняющих пробелов — частая причина «пустого» результата.

Соединения таблиц задаются конструкцией СОЕДИНЕНИЕ: ЛЕВОЕ, ПРАВОЕ, ВНУТРЕННЕЕ или ПОЛНОЕ. Чаще всего используется ЛЕВОЕ СОЕДИНЕНИЕ — оно возвращает все строки левой таблицы и подставляет NULL там, где в правой таблице пары не нашлось. Внутреннее соединение оставляет только строки, имеющие совпадение с обеих сторон.

bsl
ВЫБРАТЬ
	Номенклатура.Ссылка КАК Товар,
	ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
	Справочник.Номенклатура КАК Номенклатура
	ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
	ПО Номенклатура.Ссылка = Остатки.Номенклатура
ГДЕ
	Номенклатура.ЭтоГруппа = ЛОЖЬ

Группировка требует соблюдать правило: в списке выбранных полей могут быть либо поля, перечисленные в СГРУППИРОВАТЬ ПО, либо агрегатные функции. Если добавить «лишнее» поле без группировки, платформа выдаст ошибку. Функция ЕСТЬNULL(Поле, Значение) незаменима при соединениях — она заменяет NULL на ноль или пустую строку, иначе арифметика с NULL даст NULL.

Виртуальные таблицы регистров

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

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

Виртуальная таблица или физическая

Виртуальная таблица (Остатки, Обороты)

Подходит для получения итогов на дату или за период; быстрее и короче, но требует правильных параметров

Физическая таблица регистра

Подходит, когда нужны сами движения — документы-регистраторы, номера строк, моменты времени; для итогов используйте только с группировкой

Типичные ошибки и проверка результата

Первая группа ошибок — логические: запрос выполняется, но возвращает не то. Классический пример — соединение без достаточного условия, при котором строки перемножаются (декартово произведение), и суммы в итоге задваиваются или застраиваются. Второй пример — забытый отбор по пометке удаления или проведённости документов, из-за чего в выборку попадает «мусор».

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

Типичные ошибки
01
Отбор в секции ГДЕ вместо параметров виртуальной таблицы — резкое замедление запроса на больших данных
02
Соединение по части ключевых полей — задвоение строк и неверные суммы в итогах
03
Забытый ЕСТЬNULL после левого соединения — NULL вместо нуля ломает расчёты и сравнения
04
Сравнение строк через «=» без учёта пробелов — запрос возвращает пустой результат
05
Неустановленный параметр &Параметр — ошибка выполнения на этапе Выполнить()
06
Выборка всех полей (звёздочкой или списком «про запас») — лишняя нагрузка и память
Контрольные точки

Как проверить результат

Количество строк результата
Норма

Совпадает с ожидаемым числом объектов или групп

Тревожный признак

Строк заметно больше — вероятно перемножение при соединении

Суммы по числовым полям
Норма

Сходятся со штатным отчётом конфигурации за тот же период

Тревожный признак

Суммы кратно завышены — проверяйте условия соединения и группировку

Значения в колонках после соединения
Норма

Нули или пустые значения там, где нет данных

Тревожный признак

NULL в числовых полях — добавьте ЕСТЬNULL

Время выполнения
Норма

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

Тревожный признак

Запрос «висит» — перенесите отборы в параметры виртуальной таблицы

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

Итог

Что важно запомнить

Запрос состоит из секций ВЫБРАТЬ / ИЗ / ГДЕ и выполняется через объект Запрос с обязательной установкой параметров. Итоги берите из виртуальных таблиц с отборами в параметрах, после левых соединений применяйте ЕСТЬNULL, а результат сверяйте со штатными отчётами до использования в прикладной логике.

Частые вопросы

Чем запрос отличается от обхода справочника через Выбрать()?

Метод Выбрать() объекта перебирает записи по одной и переносит обработку в код — это медленно на больших объёмах и не умеет соединять данные разных таблиц. Запрос выполняется целиком на стороне СУБД, умеет соединения, группировки и итоги, поэтому для выборок и отчётов всегда предпочтительнее.

Как передать в запрос список значений для отбора?

Поместите значения в массив или список значений, передайте его через УстановитьПараметр, а в тексте запроса используйте условие «Поле В (&Список)». Платформа сама развернёт коллекцию в набор условий. Передавать список строкой через конкатенацию текста запроса нельзя — это небезопасно и ломает типизацию.

Почему запрос возвращает NULL вместо остатка?

Потому что при левом соединении для строк без пары в правой таблице все поля правой таблицы равны NULL, а не нулю. Оберните такое поле в функцию ЕСТЬNULL(Поле, 0). Это же правило действует для строковых полей — заменяйте NULL на пустую строку.

Можно ли использовать запрос в управляемой форме и на клиенте?

Напрямую объект Запрос доступен только на сервере. В управляемых формах запрос выполняют в серверной процедуре (с директивой &НаСервере), а результат передают на клиент в виде таблицы значений или массива структур. Либо используют динамический список формы, где запрос задаётся в свойствах реквизита.

Что такое пакетный запрос и когда он нужен?

Пакетный запрос — несколько запросов в одном тексте, разделённых точкой с запятой. Результаты промежуточных запросов можно помещать во временные таблицы (ПОМЕСТИТЬ ИмяТаблицы) и использовать в следующих запросах пакета. Это удобно для сложных выборок: сначала отобрать данные во временную таблицу, потом соединять и группировать её. Результаты пакета получают методом ВыполнитьПакет().

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

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