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

Разработка и Конфигурация · 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 (ограничение доступа на уровне записей) платформа автоматически добавляет условия, что может замедлять запрос.

Ещё одно ограничение — типы полей. Сравнение значений разных типов (например, строки с числом) не вызывает ошибку, а просто даёт ЛОЖЬ, из-за чего строки молча отбрасываются. Для полей составного типа условие следует строить с учётом всех возможных типов или приводить значения функцией ВЫРАЗИТЬ.

Типичные ошибки
01
Сравнение поля = NULL вместо ЕСТЬ NULL — условие никогда не выполняется, строки теряются
02
Отбор по измерениям регистра в ГДЕ вместо параметров виртуальной таблицы — резкое падение скорости
03
Склейка значений в текст запроса вместо параметров — ошибки формата и перекомпиляция
04
Отбор по правой таблице в ГДЕ при левом соединении — соединение превращается во внутреннее
05
Разыменование через точку в цикле или для множества полей — лишние скрытые соединения
06
Условия И/ИЛИ без скобок — неожиданный приоритет операций искажает отбор

Практический порядок построения запроса

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

Порядок действий
  1. 1
    Определите источник: справочник, документ или виртуальная таблица регистра
  2. 2
    Напишите ВЫБРАТЬ и ИЗ с псевдонимами, выполните запрос без отборов
  3. 3
    Добавьте отборы: в параметры виртуальной таблицы для регистров, в ГДЕ — для остального
  4. 4
    Замените все переменные значения параметрами &Имя и установите их в коде
  5. 5
    Добавьте соединения, обернув поля правых таблиц в ЕСТЬNULL
  6. 6
    Проверьте результат в консоли запросов: количество строк, NULL, скорость
Итог

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

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

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

Чем запрос 1С отличается от SQL-запроса к базе?

Запрос 1С обращается к объектам метаданных (справочникам, документам, регистрам), а не к физическим таблицам СУБД. Платформа сама транслирует его в SQL конкретной базы. Поэтому в языке 1С есть виртуальные таблицы и функции вроде ЗНАЧЕНИЕ, но нет прямого доступа к индексам, хинтам и служебным таблицам СУБД.

Как отобрать документы за период?

Используйте условие Документ.Дата МЕЖДУ &Начало И &Конец в секции ГДЕ таблицы документа. Учтите, что дата документа включает время; для границы конца периода применяйте функцию КонецПериода или КонецДня на встроенном языке, чтобы не потерять документы последнего дня.

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

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

Почему запрос с условием В (&Список) возвращает пустой результат?

Чаще всего параметр не установлен или передана пустая коллекция. Проверьте, что УстановитьПараметр вызван до Выполнить и что массив или список значений заполнен. Также убедитесь, что типы элементов списка совпадают с типом сравниваемого поля — сравнение ссылки со строкой молча даст ЛОЖЬ.

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

Через ОБЪЕДИНИТЬ ВСЕ: каждый подзапрос выбирает один вид документа с одинаковым набором полей, а результаты складываются в одну таблицу. Поля в объединении должны совпадать по количеству и быть совместимы по типам; имена берутся из первого подзапроса.

Что делать, если запрос выполняется слишком долго?

Сначала перенесите отборы по измерениям и периоду регистров в параметры виртуальных таблиц. Затем уберите разыменования через точку, заменив их явными соединениями, и сократите список выбираемых полей. Если этого недостаточно, анализируйте план запроса на стороне СУБД и проверяйте наличие индексов по полям отборов и соединений.