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