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