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

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

Как добавить условие в запросе 1С

Как добавить условие в запросе 1С: секция ГДЕ, операторы сравнения, ВТаблице, параметры, условия в виртуальных таблицах и типичные ошибки с примерами кода.

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

В языке запросов 1С условия можно задавать в нескольких местах: в секции ГДЕ, в параметрах виртуальных таблиц, в условиях соединения таблиц и в секции ИМЕЮЩИЕ для итоговых данных. У каждого варианта свои особенности, и выбор места для условия влияет как на результат, так и на производительность.

Ниже разобраны основные способы добавления условий: от простого сравнения с параметром до отборов по вложенным запросам и спискам значений. Все примеры можно проверить в консоли запросов на тестовой копии базы.

Базовый синтаксис секции ГДЕ

Секция ГДЕ (WHERE) размещается после описания источников данных и содержит логическое выражение. Записи, для которых выражение истинно, попадают в результат. Простейший пример — отбор документов по конкретному контрагенту:

ВЫБРАТЬ

РеализацияТоваровУслуг.Номер,

РеализацияТоваровУслуг.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

ГДЕ

РеализацияТоваровУслуг.Контрагент = &Контрагент

Параметр обозначается символом амперсанда (&) и передаётся в запрос через метод УстановитьПараметр перед выполнением. Использование параметров вместо подстановки значений прямо в текст — обязательное правило: это защищает от ошибок с типами данных и делает запрос безопасным.

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

ГДЕ

(РеализацияТоваровУслуг.Проведен = ИСТИНА

И РеализацияТоваровУслуг.СуммаДокумента > 100000)

ИЛИ РеализацияТоваровУслуг.Контрагент = &ОсновнойКонтрагент

Операторы сравнения и специальные конструкции

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

ОператорНазначениеПример
=, <>, >, <, >=, <=Сравнение значенийКоличество > 0
ВПроверка вхождения в список или результат подзапросаСклад В (&СписокСкладов)
В ИЕРАРХИИПроверка вхождения в группу иерархического справочникаНоменклатура В ИЕРАРХИИ(&Группа)
ПОДОБНОПоиск по шаблону строки с символами % и _Наименование ПОДОБНО "%кабель%"
МЕЖДУПроверка попадания в диапазон включительноДата МЕЖДУ &Начало И &Конец
ЕСТЬ NULLПроверка на незаполненное значениеКомментарий ЕСТЬ NULL
ЕСТЬ NULL / НЕ ... ЕСТЬ NULLПроверка на NULLПоле ЕСТЬ NULL

Оператор ПОДОБНО работает медленно, если шаблон начинается с символа %, потому что индекс по полю в этом случае не используется. Если нужен поиск по началу строки, ставьте шаблон вида «кабель%» — такой запрос сможет использовать индекс.

Для проверки пустых ссылок используется конструкция ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) либо сравнение с NULL, если поле может быть не заполнено из-за соединения таблиц. Помните: NULL не равен ничему, даже другому NULL, поэтому проверка делается только через ЕСТЬ NULL.

Условия с параметрами и списками значений

Передача параметра — стандартный способ сделать запрос универсальным. В коде модуля параметр устанавливается до выполнения запроса:

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

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

"ВЫБРАТЬ

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

|ИЗ

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

|ГДЕ

| Номенклатура.Родитель В ИЕРАРХИИ(&Группа)

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

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

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

Когда нужно отобрать по нескольким значениям, параметру присваивается массив или список значений, а в тексте используется оператор В. Это удобнее, чем перечислять условия через ИЛИ, и работает быстрее:

СписокСкладов = Новый Массив;

СписокСкладов.Добавить(СкладОсновной);

СписокСкладов.Добавить(СкладРезервный);

Запрос.УстановитьПараметр("Склады", СписокСкладов);

// в тексте запроса: ГДЕ Остатки.Склад В (&Склады)

Типичные ошибки
01
Подстановка значений прямо в текст запроса вместо параметров — ломается при смене типа данных и создаёт риск ошибок
02
Сравнение с NULL через знак равенства — условие никогда не сработает, нужен ЕСТЬ NULL
03
Использование ПОДОБНО с шаблоном «%текст%» на больших таблицах — полное сканирование вместо индекса
04
Забытый вызов УстановитьПараметр — запрос падает с ошибкой «Параметр не найден»

Условия в виртуальных таблицах

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

ВЫБРАТЬ

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

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

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(

&ДатаОстатков,

Склад = &Склад

И Номенклатура В (&СписокНоменклатуры)) КАК Остатки

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

У среза последних (СрезПоследних) и среза первых параметром передаётся период и условие по измерениям. Условие по ресурсам в параметрах виртуальной таблицы задать нельзя — такие отборы делаются только в ГДЕ.

Если в параметрах виртуальной таблицы условие записано через точку от псевдонима (например, Таб.Склад = &Склад), платформа выдаст ошибку — внутри скобок поля указываются без псевдонима таблицы.
ПЗ
Практическое замечание

Условия через вложенные запросы и соединения

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

ГДЕ

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

(ВЫБРАТЬ РАЗЛИЧНЫЕ

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

ИЗ

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

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

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

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

Как выбрать место для условия

Нужно отобрать данные виртуальной таблицы регистраЗадайте условие в параметрах виртуальной таблицы в круглых скобках
Нужен отбор по полю обычной таблицы или документаИспользуйте секцию ГДЕ с параметром
Условие накладывается на сгруппированные итогиИспользуйте секцию ИМЕЮЩИЕ после СГРУППИРОВАТЬ ПО
Условие относится к правой таблице левого соединенияПеренесите его в секцию ПО условия соединения

Секция ИМЕЮЩИЕ и условия по итогам

Секция ГДЕ не может содержать агрегатные функции — СУММА, КОЛИЧЕСТВО, МАКСИМУМ и другие. Если нужно отобрать группы по результату агрегации, например клиентов с суммой продаж выше порога, условие пишется в секции ИМЕЮЩИЕ после группировки:

ВЫБРАТЬ

Продажи.Контрагент,

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

ИЗ

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

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

Продажи.Контрагент

ИМЕЮЩИЕ

СУММА(Продажи.СуммаОборот) > &МинимальнаяСумма

Логика выполнения такова: сначала применяется ГДЕ к строкам, затем данные группируются, и только после этого ИМЕЮЩИЕ отбрасывает неподходящие группы. Поэтому условия по обычным полям выгоднее держать в ГДЕ — они уменьшают объём данных до группировки.

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

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

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

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

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

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

Меньше или равно количеству без условия, соответствует ожидаемому отбору

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

Ноль записей при заведомо существующих данных или полный список без фильтрации

Типы параметров
Норма

Тип параметра совпадает с типом поля в базе

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

Строка передаётся вместо ссылки или даты — условие не срабатывает

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

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

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

Резкое замедление после добавления условия с ПОДОБНО или вложенным запросом

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

Как добавить условие «не равно» в запросе 1С?

Используйте оператор <>, например: ГДЕ Номенклатура.ПометкаУдаления = ЛОЖЬ или ГДЕ Статус <> ЗНАЧЕНИЕ(Перечисление.Статусы.Закрыт). Для исключения значения из списка применяется конструкция НЕ Поле В (&Список).

Можно ли использовать функции в условии ГДЕ?

Да, в условиях доступны встроенные функции языка запросов: ДАТАВРЕМЯ, НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ПОДСТРОКА и другие. Например: ГДЕ Продажи.Период >= НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ). Учтите, что функция над полем таблицы может отключить использование индекса.

Почему условие с параметром-списком не работает?

Чаще всего причина в том, что параметру присвоено одиночное значение вместо массива или списка значений, либо элементы списка имеют другой тип. Проверьте, что в УстановитьПараметр передаётся именно коллекция, а тип её элементов совпадает с типом поля.

Чем отличается ГДЕ от ИМЕЮЩИЕ?

ГДЕ фильтрует строки до группировки и не может содержать агрегатные функции. ИМЕЮЩИЕ применяется к сгруппированным данным и работает с агрегатами — СУММА, КОЛИЧЕСТВО и другими. Если условие не требует агрегации, всегда размещайте его в ГДЕ: это быстрее.

Как задать условие «или» по нескольким полям?

Перечислите условия через оператор ИЛИ и обязательно оберните группу в скобки, если рядом есть условия через И: ГДЕ (Поле1 = &Значение1 ИЛИ Поле2 = &Значение2) И Проведен = ИСТИНА. Без скобок приоритет И выше, и логика запроса исказится.

Где лучше ставить условие для регистра остатков?

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

Итог

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

Основной инструмент условий — секция ГДЕ с параметрами через &. Для виртуальных таблиц условия задавайте в их параметрах, для итогов — в ИМЕЮЩИЕ, для соединений — в ПО. Проверяйте типы параметров, используйте ЕСТЬ NULL вместо сравнения с NULL и отлаживайте запросы на копии базы.