Разработка и Конфигурация · 12 мин
Как сформировать запрос в 1С: пошаговое руководство
Как сформировать запрос в 1С: работа с конструктором запроса, синтаксис языка запросов, выборки, условия, соединения и группировки с примерами кода.
Запрос в 1С — основной инструмент получения данных из информационной базы: остатков по складу, оборотов по счетам, списков документов и любых выборок для отчётов. В отличие от прямого перебора объектов, запрос выполняется на стороне СУБД, поэтому работает быстрее и корректнее при больших объёмах данных. Умение грамотно формировать запрос — базовый навык разработчика и продвинутого пользователя, строящего отчёты.
Язык запросов 1С похож на SQL, но адаптирован под структуру конфигурации: вместо таблиц базы данных используются объекты метаданных — справочники, документы, регистры накопления и сведений. Составить запрос можно двумя способами: визуально через конструктор запроса или вручную, написав текст запроса в модуле. Оба подхода дают одинаковый результат, разница только в скорости разработки и контроле над деталями.
Ниже разобраны оба способа, базовый синтаксис, типовые приёмы (условия, соединения, группировки, виртуальные таблицы) и ошибки, которые чаще всего приводят к медленным или неверным выборкам.
Как сформировать запрос через конструктор
Конструктор запроса — встроенный визуальный инструмент конфигуратора. Он открывается из любого модуля: правый клик в тексте модуля → «Конструктор запроса». Если курсор стоит внутри строки с текстом запроса, конструктор загрузит существующий запрос для редактирования; если в пустом месте — предложит создать новый.
Работа в конструкторе строится по вкладкам. На вкладке «Таблицы и поля» в левой части выбирается объект метаданных (например, регистр накопления «ТоварыНаСкладах»), он переносится в список таблиц, после чего из таблицы выбираются нужные поля. На вкладке «Связи» настраиваются соединения нескольких таблиц, на вкладке «Условия» — отборы, на вкладке «Группировка» — итоги и агрегатные функции. Вкладка «Итоги» отвечает за итоговые записи по группам.
- 1Откройте модуль и вызовите конструктор запроса через контекстное меню
- 2На вкладке «Таблицы и поля» выберите нужный справочник, документ или регистр
- 3Перенесите требуемые поля в список выбранных полей
- 4Задайте условия отбора на вкладке «Условия», используя параметры (&Параметр)
- 5При необходимости настройте группировку и итоги
- 6Нажмите «ОК» — конструктор сформирует текст запроса и заготовку кода
После нажатия «ОК» конструктор вставит в модуль не только текст запроса, но и шаблон кода: создание объекта Запрос, присвоение текста, выполнение и обход выборки. Это удобная отправная точка, но код почти всегда требует доработки — передачи параметров и обработки результата под конкретную задачу.
Базовый синтаксис языка запросов 1С
Минимальный запрос состоит из двух обязательных секций: ВЫБРАТЬ (какие поля нужны) и ИЗ (откуда их брать). Таблицы указываются через точку по типу объекта: Справочник.Номенклатура, Документ.РеализацияТоваров, РегистрНакопления.Продажи. Регистры сведений обозначаются как РегистрСведений.ИмяРегистра.
Дополнительные секции расширяют выборку: ГДЕ — отбор строк по условию, УПОРЯДОЧИТЬ ПО — сортировка, СГРУППИРОВАТЬ ПО — группировка с агрегатными функциями СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. Ключевое слово РАЗЛИЧНЫЕ убирает дубли строк, а ПЕРВЫЕ N ограничивает количество возвращаемых записей.
ВЫБРАТЬ
Товары.Ссылка КАК Номенклатура,
Товары.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.ЭтоГруппа = ЛОЖЬ
И Товары.ПометкаУдаления = ЛОЖЬ
УПОРЯДОЧИТЬ ПО
Товары.НаименованиеКаждой таблице принято давать псевдоним через КАК — это делает запрос читаемым и обязательно при соединении нескольких таблиц, где имена полей могут совпадать. Полям результата тоже задают псевдонимы, чтобы потом обращаться к ним в коде по понятному имени.
Как выполнить запрос программно и передать параметры
Текст запроса сам по себе ничего не делает — его нужно выполнить через объект встроенного языка. Стандартная последовательность: создать объект Запрос, присвоить текст, установить параметры, выполнить и обработать результат. Результат получают двумя способами: метод Выбрать() возвращает выборку для построчного обхода в цикле, метод Выгрузить() — таблицу значений целиком.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура,
| СУММА(Продажи.Количество) КАК Количество
|ИЗ
| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
|ГДЕ
| Продажи.Номенклатура = &Номенклатура
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура";
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
// обработка строки: Выборка.Номенклатура, Выборка.Количество
КонецЦикла;Параметры в тексте запроса обозначаются символом «&» и обязательно должны быть установлены до вызова Выполнить() — иначе платформа выдаст ошибку «Параметр не установлен». В параметры можно передавать примитивные значения, ссылки, даты, массивы и списки значений. Массивы особенно полезны для условий вида «Поле В (&СписокЗначений)».
Выбор между Выбрать() и Выгрузить() зависит от задачи. Выборка экономит память при обходе большого результата, но не позволяет вернуться к предыдущим строкам. Таблица значений удобна, когда данные нужно сортировать, сворачивать, искать строки или передавать между процедурами.
Как выбрать способ получения результата
Условия, соединения и группировки
Условия в секции ГДЕ поддерживают сравнения, логические И/ИЛИ, проверку на NULL (ЕСТЬ NULL / НЕ ЕСТЬ NULL), вхождение в список (В), подобие строки (ПОДОБНО с шаблоном «%текст%») и вхождение в иерархию (В ИЕРАРХИИ). Для строковых полей сравнение через «=» требует точного совпадения с учётом дополняющих пробелов — частая причина «пустого» результата.
Соединения таблиц задаются конструкцией СОЕДИНЕНИЕ: ЛЕВОЕ, ПРАВОЕ, ВНУТРЕННЕЕ или ПОЛНОЕ. Чаще всего используется ЛЕВОЕ СОЕДИНЕНИЕ — оно возвращает все строки левой таблицы и подставляет NULL там, где в правой таблице пары не нашлось. Внутреннее соединение оставляет только строки, имеющие совпадение с обеих сторон.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
ПО Номенклатура.Ссылка = Остатки.Номенклатура
ГДЕ
Номенклатура.ЭтоГруппа = ЛОЖЬГруппировка требует соблюдать правило: в списке выбранных полей могут быть либо поля, перечисленные в СГРУППИРОВАТЬ ПО, либо агрегатные функции. Если добавить «лишнее» поле без группировки, платформа выдаст ошибку. Функция ЕСТЬNULL(Поле, Значение) незаменима при соединениях — она заменяет NULL на ноль или пустую строку, иначе арифметика с NULL даст NULL.
Виртуальные таблицы регистров
Регистры накопления и сведений имеют виртуальные таблицы — готовые выборки, которые платформа рассчитывает автоматически: Остатки, Обороты, ОстаткиИОбороты для регистров накопления; СрезПервых, СрезПоследних для регистров сведений. Использовать их почти всегда правильнее, чем группировать физическую таблицу движений вручную.
Параметры виртуальной таблицы указываются в скобках после имени: период, периодичность, условие отбора. Важное правило оптимизации: отбор нужно задавать именно в параметрах виртуальной таблицы, а не в секции ГДЕ. Отбор в параметрах выполняется до формирования выборки и резко сокращает объём обрабатываемых данных.
Виртуальная таблица или физическая
Подходит для получения итогов на дату или за период; быстрее и короче, но требует правильных параметров
Подходит, когда нужны сами движения — документы-регистраторы, номера строк, моменты времени; для итогов используйте только с группировкой
Типичные ошибки и проверка результата
Первая группа ошибок — логические: запрос выполняется, но возвращает не то. Классический пример — соединение без достаточного условия, при котором строки перемножаются (декартово произведение), и суммы в итоге задваиваются или застраиваются. Второй пример — забытый отбор по пометке удаления или проведённости документов, из-за чего в выборку попадает «мусор».
Вторая группа — ошибки производительности: отбор в ГДЕ вместо параметров виртуальной таблицы, соединение по вычисляемым выражениям, выборка всех полей вместо нужных, отсутствие ограничения периода. Такие запросы на маленькой базе работают нормально, а на рабочей — выполняются минутами.
Как проверить результат
Совпадает с ожидаемым числом объектов или групп
Строк заметно больше — вероятно перемножение при соединении
Сходятся со штатным отчётом конфигурации за тот же период
Суммы кратно завышены — проверяйте условия соединения и группировку
Нули или пустые значения там, где нет данных
NULL в числовых полях — добавьте ЕСТЬNULL
Запрос с отборами выполняется за секунды на рабочем объёме
Запрос «висит» — перенесите отборы в параметры виртуальной таблицы
Для отладки удобна консоль запросов — внешняя обработка, позволяющая выполнить текст запроса с параметрами и сразу увидеть таблицу результата. Также полезен метод Результат.Выгрузить() с последующим просмотром таблицы значений в отладчике: так видно реальные типы и значения колонок, включая NULL.
Что важно запомнить
Запрос состоит из секций ВЫБРАТЬ / ИЗ / ГДЕ и выполняется через объект Запрос с обязательной установкой параметров. Итоги берите из виртуальных таблиц с отборами в параметрах, после левых соединений применяйте ЕСТЬNULL, а результат сверяйте со штатными отчётами до использования в прикладной логике.
Частые вопросы
Чем запрос отличается от обхода справочника через Выбрать()?
Метод Выбрать() объекта перебирает записи по одной и переносит обработку в код — это медленно на больших объёмах и не умеет соединять данные разных таблиц. Запрос выполняется целиком на стороне СУБД, умеет соединения, группировки и итоги, поэтому для выборок и отчётов всегда предпочтительнее.
Как передать в запрос список значений для отбора?
Поместите значения в массив или список значений, передайте его через УстановитьПараметр, а в тексте запроса используйте условие «Поле В (&Список)». Платформа сама развернёт коллекцию в набор условий. Передавать список строкой через конкатенацию текста запроса нельзя — это небезопасно и ломает типизацию.
Почему запрос возвращает NULL вместо остатка?
Потому что при левом соединении для строк без пары в правой таблице все поля правой таблицы равны NULL, а не нулю. Оберните такое поле в функцию ЕСТЬNULL(Поле, 0). Это же правило действует для строковых полей — заменяйте NULL на пустую строку.
Можно ли использовать запрос в управляемой форме и на клиенте?
Напрямую объект Запрос доступен только на сервере. В управляемых формах запрос выполняют в серверной процедуре (с директивой &НаСервере), а результат передают на клиент в виде таблицы значений или массива структур. Либо используют динамический список формы, где запрос задаётся в свойствах реквизита.
Что такое пакетный запрос и когда он нужен?
Пакетный запрос — несколько запросов в одном тексте, разделённых точкой с запятой. Результаты промежуточных запросов можно помещать во временные таблицы (ПОМЕСТИТЬ ИмяТаблицы) и использовать в следующих запросах пакета. Это удобно для сложных выборок: сначала отобрать данные во временную таблицу, потом соединять и группировать её. Результаты пакета получают методом ВыполнитьПакет().
Как отладить запрос, не изменяя код модуля?
Скопируйте текст запроса в консоль запросов (типовая возможность инструментов разработчика или отдельная внешняя обработка), задайте параметры вручную и выполните. Консоль покажет таблицу результата и текст ошибки, если она есть. Дополнительно удобно ограничить выборку конструкцией ПЕРВЫЕ 100, чтобы не нагружать базу при отладке.