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

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

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

Практическое руководство по созданию запросов в 1С: конструктор запроса, синтаксис языка, параметры, виртуальные таблицы, типичные ошибки и проверка результата.

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

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

Где создаются запросы и какой инструмент выбрать

Текст запроса встречается в нескольких местах конфигурации: в модулях объектов и форм (объект «Запрос»), в схеме компоновки данных для отчётов на СКД, в динамических списках и в обработках. Во всех случаях синтаксис один и тот же, отличается только способ выполнения: программно через Запрос.Выполнить() или автоматически платформой при открытии отчёта.

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

Чем создавать запрос

Конструктор запроса

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

Ручное написание

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

Консоль запросов

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

Создание запроса через конструктор: пошагово

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

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

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

Синтаксис языка запросов: минимальный набор

Язык запросов 1С напоминает SQL, но ключевые слова пишутся на русском. Минимальный запрос состоит из секций ВЫБРАТЬ и ИЗ. Секция ГДЕ задаёт отбор, УПОРЯДОЧИТЬ ПО — сортировку, СГРУППИРОВАТЬ ПО с агрегатными функциями СУММА, КОЛИЧЕСТВО, МАКСИМУМ — группировку. Допускается и английский синтаксис (SELECT, FROM, WHERE), платформа понимает оба варианта.

Пример простого запроса к справочнику с отбором по параметру:

ВЫБРАТЬ

Номенклатура.Ссылка,

Номенклатура.Наименование,

Номенклатура.Артикул

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Родитель = &Группа

И НЕ Номенклатура.ПометкаУдаления

УПОРЯДОЧИТЬ ПО

Номенклатура.Наименование

Обратите внимание на псевдоним таблицы после КАК: он упрощает чтение и обязателен при соединении нескольких таблиц. Оператор «НЕ» исключает помеченные на удаление элементы — частый источник ошибок, когда в отчёт попадают «мёртвые» записи. В условиях доступны сравнения, В (список), МЕЖДУ, ПОДОБНО для поиска по шаблону и проверка ЕСТЬ NULL.

Параметры запроса и их установка

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

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

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ..."; // текст из примера выше

Запрос.УстановитьПараметр("Группа", ВыбраннаяГруппа);

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

// обработка строки выборки

КонецЦикла;

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

Когда данные лежат в разных объектах, таблицы соединяют в секции ИЗ. Левое соединение (ЛЕВОЕ СОЕДИНЕНИЕ) возвращает все строки левой таблицы и совпадения из правой — это основной тип связи в учётных задачах. Внутреннее соединение оставляет только пары, где есть совпадение с обеих сторон. Условие связи пишется после ПО, например по полю «Ссылка».

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

ВЫБРАТЬ

Остатки.Номенклатура,

Остатки.КоличествоОстаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, Склад = &Склад) КАК Остатки

Обработка результата: выборка, выгрузка, проверка

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

Перед обходом полезно проверить Результат.Пустой, чтобы не выполнять лишнюю работу при пустом ответе. Если запрос с группировкой, в выборке доступны итоги: метод Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) позволяет обойти иерархию итогов и детальных записей.

Контрольные точки

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

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

Совпадает с ожиданием по контрольному примеру или отчёту за тот же период

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

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

Суммы по группировке
Норма

Сходятся с типовым отчётом по тому же регистру

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

Суммы завышены кратно — вероятно, дублирование строк из-за соединения без достаточного условия связи

Поля из соединённой таблицы
Норма

Заполнены там, где связь существует, NULL там, где её нет

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

NULL во всех строках — неверное условие соединения

Типичные ошибки и ограничения

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

Есть и ограничения платформы. Запрос не может изменять данные — только читать. В запросе нельзя вызывать произвольные функции встроенного языка, доступны только операции языка запросов. Обращение к реквизитам через точку от ссылки («разыменование») допустимо, но злоупотребление им в больших выборках замедляет выполнение — лучше соединить таблицы явно.

Типичные ошибки
01
Подстановка значений в текст запроса конкатенацией вместо параметров — ломает производительность и ведёт к ошибкам на спецсимволах
02
Отбор из виртуальной таблицы в секции ГДЕ вместо параметров виртуальной таблицы — платформа сначала вычислит все остатки, потом отфильтрует, запрос станет медленным
03
Отсутствие отбора по ПометкаУдаления — в выборку попадают удалённые объекты
04
Соединение без полного условия связи — дублирование строк и завышенные итоги
05
Использование Выгрузить() для миллионов строк — избыточный расход памяти, где достаточно обхода выборки

Как выбрать подход под конкретную задачу

Для разовой выборки в модуле документа достаточно простого запроса с параметрами. Для отчёта, который пользователь будет настраивать сам, правильнее схема компоновки данных: запрос пишется один раз, а отборы, группировки и поля пользователь меняет в настройках без программирования. Для списков на форме используйте динамический список с произвольным запросом — он сам обрабатывает сортировку и отбор.

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

Как выбрать действие

Нужна разовая выборка в коде обработки или модуляСоздайте объект Запрос, задайте текст, установите параметры и обойдите выборку
Пользователь должен сам менять отборы и группировки отчётаИспользуйте схему компоновки данных — запрос пишется один раз, настройки делает пользователь
Запрос работает медленно на больших данныхПеренесите отборы в параметры виртуальных таблиц и проверьте наличие индексов по полям связи
Нужны остатки или обороты за периодИспользуйте виртуальные таблицы регистра, а не суммирование движений вручную
Итог

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

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

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

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

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

Можно ли в запросе отобрать по нескольким значениям одного поля?

Да. Передайте в параметр массив или список значений и используйте оператор В: ГДЕ Номенклатура.Родитель В (&СписокГрупп). Платформа корректно развернёт список в условие на стороне СУБД.

Почему запрос с виртуальной таблицей возвращает пустой результат?

Чаще всего дело в параметрах виртуальной таблицы: дата остатков раньше первых движений, отбор по складу или организации не совпадает с данными, либо регистр вообще не заполнен. Проверьте те же данные типовым отчётом по регистру — если и там пусто, проблема в данных, а не в запросе.

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

Для табличного документа используйте макет с областями и построчный вывод из выборки. Для формы выгрузите результат методом Выгрузить() в таблицу значений и привяжите её к реквизиту формы типа «ТаблицаЗначений». Для отчётов предпочтительна СКД — она выводит результат без ручного кода.

Работает ли язык запросов одинаково на разных СУБД?

Да, это одно из назначений языка запросов: платформа транслирует один и тот же текст в диалекты MS SQL Server, PostgreSQL, Oracle и IBM Db2. Однако планы выполнения на разных СУБД могут отличаться, поэтому тяжёлые запросы стоит проверять на той СУБД, которая используется в рабочей базе.