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