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

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

Как строить запросы в 1С

Как писать запросы на языке запросов 1С: синтаксис ВЫБРАТЬ, отборы, соединения, группировки, конструктор запроса, типовые ошибки и проверка результата.

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

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

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

Структура запроса: из чего состоит текст

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

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

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

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

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

|ИЗ

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

|ГДЕ

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

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

Обратите внимание на псевдонимы: КАК Товар задаёт имя поля в результате, КАК Номенклатура после источника — псевдоним таблицы. Псевдонимы делают запрос читаемым и обязательны при соединениях нескольких таблиц, чтобы однозначно указать, из какого источника берётся поле.

Как собрать запрос конструктором без ручного набора текста

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

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

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

Соединения таблиц: левое, внутреннее и когда какое нужно

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

ВЫБРАТЬ

Товары.Ссылка КАК Товар,

ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Товары.Ссылка = Остатки.Номенклатура

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

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

Какой тип соединения выбрать

ЛЕВОЕ СОЕДИНЕНИЕ

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

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

Нужны только пары с гарантированной связью: документы, у которых есть движения по регистру

ПОЛНОЕ СОЕДИНЕНИЕ

Нужны все записи обеих таблиц; применяется редко, например при сверке двух источников

Группировки, итоги и виртуальные таблицы регистров

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

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

ВЫБРАТЬ

Продажи.Номенклатура КАК Товар,

СУММА(Продажи.КоличествоОборот) КАК Продано,

СУММА(Продажи.СуммаОборот) КАК Выручка

ИЗ

РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

СГРУППИРОВАТЬ ПО

Продажи.Номенклатура

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

Выручка УБЫВ

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

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

Обработка результата: выборка, таблица значений и пакетные запросы

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

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

ВЫБРАТЬ

Движения.Номенклатура КАК Товар,

СУММА(Движения.Количество) КАК Количество

ПОМЕСТИТЬ ВТ_Продажи

ИЗ

РегистрНакопления.Продажи КАК Движения

ГДЕ

Движения.Период МЕЖДУ &Начало И &Конец

СГРУППИРОВАТЬ ПО

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

;

ВЫБРАТЬ

ВТ_Продажи.Товар,

ВТ_Продажи.Количество

ИЗ

ВТ_Продажи КАК ВТ_Продажи

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

Типичные ошибки
01
Запрос в цикле: обращение к базе на каждой итерации вместо одного запроса с соединением — резкое падение производительности
02
Отбор по результату соединения вместо параметров виртуальной таблицы — лишнее сканирование данных
03
Забытый ЕСТЬNULL после левого соединения — значения NULL ломают сравнения и арифметику в коде
04
Соединение без проверки уникальности связи — дубли строк и завышенные суммы в отчётах
05
Подстановка пользовательского ввода прямо в текст запроса — ошибки синтаксиса и риск порчи данных
06
Использование ПЕРВЫЕ без УПОРЯДОЧИТЬ ПО — непредсказуемый набор строк в результате

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

Первый уровень проверки — выполнение в консоли запросов на копии базы. Консоль запросов (внешняя обработка или встроенная в некоторые конфигурации) позволяет выполнить текст с параметрами и сразу увидеть результат, не запуская основной код. Это самый быстрый способ отловить ошибки синтаксиса и логики.

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

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

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

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

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

Совпадает с числом записей в источнике после отбора

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

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

Суммовые показатели
Норма

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

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

Расхождения — проверьте отборы, период и виртуальные таблицы

Пустые значения
Норма

NULL обработаны через ЕСТЬNULL

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

В полях NULL, сравнения и расчёты ведут себя непредсказуемо

Скорость выполнения
Норма

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

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

Выполнение занимает десятки секунд — нужна оптимизация отборов

Частые вопросы о запросах в 1С

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

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

Можно ли использовать в запросе поля через точку, например Контрагент.ИНН?

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

Как ограничить количество возвращаемых строк?

Используйте конструкцию ВЫБРАТЬ ПЕРВЫЕ N, где N — число строк. Обязательно сочетайте её с УПОРЯДОЧИТЬ ПО, иначе платформа вернёт произвольные записи, и результат будет отличаться от запуска к запуску.

Почему запрос с условием ПОДОБНО работает медленно?

Если маска начинается с символа процента (например, ПОДОБНО "%текст"), СУБД не может использовать индекс и сканирует всю таблицу. По возможности задавайте префикс без начального процента или ищите по отдельному индексированному реквизиту.

Нужно ли знать SQL, чтобы писать запросы в 1С?

Не обязательно. Язык запросов 1С самодостаточен и описан в синтакс-помощнике конфигуратора. Знание SQL помогает понять принципы соединений и группировок, но прямой доступ к СУБД минуя платформу использовать нельзя — это нарушает логику работы с данными.

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

Выгрузите таблицу значений в параметр через УстановитьПараметр, затем в первом запросе пакета выберите её поля с ПОМЕСТИТЬ во временную таблицу. Дальше временная таблица участвует в соединениях как обычный источник. Не забудьте указать типы колонок при создании таблицы значений.

Итог

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

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