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

Эта статья поможет разобраться, как правильно применять ГДЕ в различных сценариях: от простых фильтров по одному полю до сложных условий с вложенными запросами и параметрами. Мы рассмотрим типичные ошибки, которые допускают даже опытные разработчики, сравним производительность разных подходов и покажем, как избежать распространённых подводных камней. Особое внимание уделим нюансам работы с датами, ссылками на объекты и динамическими параметрами — темам, которые часто вызывают вопросы у новичков.

1. Базовый синтаксис конструкции ГДЕ

Конструкция ГДЕ в запросах 1С используется для указания условий отбора данных. Она всегда следует за разделом ВЫБРАТЬ и предшествует другим секциям, таким как ГРУППИРОВКА или УПОРЯДОЧИТЬ ПО. Общий вид:

ВЫБРАТЬ

Поле1, Поле2

ИЗ

Таблица

ГДЕ

Условие1 И Условие2

Например, запрос с фильтром по дате будет выглядеть так:

ВЫБРАТЬ

Дата, Сумма

ИЗ

Документ.ПоступлениеТоваров

ГДЕ

Дата >= &НачалоПериода И Дата <= &КонецПериода

Обратите внимание на использование параметров (&НачалоПериода). Это позволяет динамически подставлять значения при выполнении запроса, что особенно удобно в отчётах. Однако есть нюанс: если параметр не будет передан, запрос завершится с ошибкой. Чтобы избежать этого, можно задать значение по умолчанию прямо в тексте запроса:

ГДЕ

Дата >= &НачалоПериода(ТЕКУЩАЯДАТА())

💡

Если в запросе используется много параметров, лучше вынести их объявление в отдельный раздел ПАРАМЕТРЫ в начале текста запроса. Это улучшит читаемость и упростит поддержку кода.

2. Логические операторы и их приоритеты

В конструкции ГДЕ можно комбинировать условия с помощью логических операторов. Основные из них:

  • 🔹 И — логическое И (аналог AND в SQL). Условия должны выполняться одновременно.
  • 🔹 ИЛИ — логическое ИЛИ (аналог OR). Достаточно выполнения хотя бы одного условия.
  • 🔹 НЕ — отрицание (аналог NOT). Инвертирует условие.

Приоритет операторов в 1С совпадает с SQL: сначала выполняется НЕ, затем И, и только потом ИЛИ. Чтобы избежать неоднозначностей, рекомендуется использовать скобки для явного указания порядка вычислений. Например:

ГДЕ

(ТипДокумента = &Тип1 ИЛИ ТипДокумента = &Тип2)

И НЕ ПометкаУдаления

Без скобок этот запрос мог бы интерпретироваться иначе: сначала применилось бы И к ТипДокумента = &Тип2 и НЕ ПометкаУдаления, а затем результат объединился бы с первым условием через ИЛИ.

📊 Как часто вы используете скобки в условиях ГДЕ?
Всегда
Только когда необходимо
Рядом никогда
Не знаю, что это

3. Работа с датами и временными интервалами

Фильтрация по датам — одна из самых распространённых задач в запросах 1С. Здесь есть несколько важных моментов:

  • 📅 Даты в условиях сравниваются как дата-время, даже если поле имеет тип Дата. Это означает, что условие Дата = &ТекущаяДата может не сработать, если в поле хранится время (например, 12:00:00).
  • 🕒 Для точного сравнения дат без учёта времени используйте функции НАЧАЛОДНЯ() и КОНЕЦДНЯ():
ГДЕ

Дата >= НАЧАЛОДНЯ(&ТекущаяДата)

И Дата <= КОНЕЦДНЯ(&ТекущаяДата)

Если нужно отфильтровать данные за текущий месяц или год, удобно использовать функции НАЧАЛОМЕСЯЦА(), НАЧАЛОГОДА() и их аналоги для конца периода. Например, запрос за текущий квартал:

ГДЕ

Дата >= НАЧАЛОКВАРТАЛА(ТЕКУЩАЯДАТА())

И Дата <= КОНЕЦКВАРТАЛА(ТЕКУЩАЯДАТА())

Для работы с интервалами (например, "за последние 30 дней") можно использовать арифметические операции с датами:

ГДЕ

Дата >= ТЕКУЩАЯДАТА() - 30

Что будет, если сравнить дату с пустым значением?

Если поле даты сравнивается с NULL (например, Дата = NULL), запрос вернёт ошибку. Вместо этого нужно использовать проверку Дата ЕСТЬ NULL или Дата ЕСТЬ NULL ИЛИ Дата = &Значение.

4. Фильтрация по ссылкам на объекты и перечислениям

В 1С часто приходится фильтровать данные по ссылкам на справочники, документы или элементы перечислений. Здесь есть свои нюансы:

  • 🔗 Для сравнения со ссылкой используйте оператор =. Например, фильтрация по конкретному контрагенту:
ГДЕ

Контрагент = &ВыбранныйКонтрагент

Если нужно отфильтровать по нескольким значениям, используйте оператор В (аналог IN в SQL):

ГДЕ

Контрагент В (&СписокКонтрагентов)

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

ГДЕ

ВидОплаты = ЗНАЧЕНИЕ(Перечисление.ВидыОплаты.Наличные)

Ошибка многих новичков — попытка сравнить перечисление со строкой (например, ВидОплаты = "Наличные"). Это приведёт к ошибке выполнения запроса.

Убедиться, что параметр содержит ссылку, а не строку|Проверить, что объект не помечен на удаление|Использовать В вместо множества ИЛИ|Учитывать права доступа к объектам-->

5. Сложные условия: подзапросы и функции

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

ВЫБРАТЬ

Номер, Дата, Сумма

ИЗ

Документ.РеализацияТоваров

ГДЕ

Сумма > (ВЫБРАТЬ СРЕДНЕЕ(Сумма) ИЗ Документ.РеализацияТоваров)

В этом примере подзапрос вычисляет среднюю сумму, а основной запрос сравнивает каждое значение с этим средним. Важно, что подзапросы в условиях ГДЕ должны возвращать одно значение (скалярный результат). Если подзапрос вернёт несколько строк, возникнет ошибка.

Другой пример — использование агрегатных функций прямо в условии. Допустим, нужно найти контрагентов, у которых сумма заказов превышает 100 000 рублей:

ВЫБРАТЬ

Контрагент

ИЗ

Документ.ЗаказПокупателя КАК Заказ

ГДЕ

Контрагент В (

ВЫБРАТЬ

Контрагент

ИЗ

Документ.ЗаказПокупателя КАК ВложенныйЗаказ

ГРУППИРОВКА ПО

Контрагент

ИМЕЮЩИЕ

СУММА(СуммаДокумента) > 100000

)

Здесь используется конструкция ИМЕЮЩИЕ (аналог HAVING в SQL) для фильтрации сгруппированных данных. Обратите внимание, что вложенный запрос возвращает список контрагентов, которые затем используются в основном запросе.

💡

Подзапросы в условиях ГДЕ могут значительно замедлить выполнение запроса. Если возможно, замените их соединениями (JOIN) или временными таблицами.

6. Оптимизация запросов с конструкцией ГДЕ

Неправильное использование ГДЕ может приводить к низкой производительности, особенно в больших базах данных. Вот несколько советов по оптимизации:

  1. 🚀 Избегайте функций в условиях. Например, запрос ГДЕ ЛЕВ(Номер, 3) = "АБВ"forced index scan, так как функция ЛЕВ() применяется к каждому значению поля. Лучше использовать ГДЕ Номер ПОДОБНО "АБВ%".
  2. 🔍 Используйте индексированные поля. Условия по индексированным полям (например, ссылки на справочники или даты) выполняются быстрее. Проверьте наличие индексов в конфигураторе.
  3. 📊 Ограничивайте объём данных. Если нужно получить только первые 100 строк, добавьте ПЕРВЫЕ 100 после ВЫБРАТЬ.

Ещё один важный момент — порядок условий. Система 1С пытается оптимизировать запрос самостоятельно, но в некоторых случаях помогает явное указание наиболее "селективных" условий (тех, которые отсекают больше строк) в начале. Например:

ГДЕ

Дата >= &НачалоПериода И Дата <= &КонецПериода -- Меньше строк

И Контрагент = &ВыбранныйКонтрагент -- Ещё меньше строк

И Сумма > 1000 -- Самое последнее

Такой порядок позволяет системе быстрее сократить объём обрабатываемых данных.

💡

Для анализа производительности запроса используйте План запроса в конфигураторе. Он покажет, какие операции наиболее затратные и где можно оптимизировать.

7. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с конструкцией ГДЕ. Рассмотрим наиболее распространённые:

Ошибка Причина Как исправить
Сравнение с NULL через = Оператор = не работает с NULL Использовать ЕСТЬ NULL или ЗНАЧЕНИЕЗАПОЛНЕНО()
Несовпадение типов данных Сравнение строки с числом или датой Привести типы к одному виду с помощью ЧИСЛО(), ДАТА() и т.д.
Использование ПОДОБНО без индекса Поиск по шаблону %текст% не использует индексы Заменить на НАЧИНАЕТСЯ С или создать полнотекстовый индекс
Слишком много условий ИЛИ Каждое ИЛИ может приводить к полному сканированию таблицы Заменить на В или использовать временные таблицы

Одна из самых коварных ошибок — неявное преобразование типов. Например, если поле Код имеет тип Строка, а вы сравниваете его с числом (ГДЕ Код = 123), система попытается автоматически преобразовать типы. В некоторых случаях это может работать, но иногда приводит к неожиданным результатам или ошибкам. Всегда следите за соответствием типов!

Ещё одна распространённая проблема — игнорирование прав доступа. Если в условии ГДЕ используется поле, к которому у пользователя нет прав, запрос может вернуть неполные данные или ошибку. Всегда проверяйте права на объекты, участвующие в фильтрации.

💡

Если запрос возвращает неожиданно мало строк, первым делом проверьте условия в ГДЕ на наличие опечаток или неверных сравнений (например, > вместо <).

8. Сравнение с SQL: ключевые различия

Те, кто пришёл в 1С из мира SQL, часто пытаются использовать привычный синтаксис, что приводит к ошибкам. Основные различия:

  • 🆚 В 1С используется ГДЕ, а не WHERE.
  • 🆚 Логические операторы пишутся по-русски: И, ИЛИ, НЕ вместо AND, OR, NOT.
  • 🆚 Для проверки на NULL используется ЕСТЬ NULL вместо IS NULL.
  • 🆚 В 1С нет оператора BETWEEN. Вместо него используют два условия с >= и <=.
  • 🆚 Подзапросы в условиях ГДЕ должны возвращать скалярное значение или список, но не таблицу.

Пример различия в синтаксисе для одного и того же запроса:

-- SQL

SELECT Name, Date

FROM Documents

WHERE Date BETWEEN '2023-01-01' AND '2023-12-31'

AND (Type = 1 OR Type = 2)

-- 1С

ВЫБРАТЬ

Наименование, Дата

ИЗ

Документы

ГДЕ

Дата >= ДАТАВРЕМЯ(2023, 1, 1, 0, 0, 0)

И Дата <= ДАТАВРЕМЯ(2023, 12, 31, 23, 59, 59)

И (Тип = &Тип1 ИЛИ Тип = &Тип2)

Ещё одно важное отличие — работа с параметрами. В SQL параметры часто обозначаются через ? или :имя, а в 1С используется префикс &. При этом в 1С параметры можно объявлять прямо в тексте запроса, что упрощает динамическое формирование условий.

Можно ли в 1С использовать псевдонимы таблиц в условиях?

Да, но синтаксис отличается от SQL. В 1С псевдонимы указываются через ключевое слово КАК, и их можно использовать в условиях ГДЕ. Например:

ВЫБРАТЬ

д.Номер

ИЗ

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

ГДЕ

д.Дата > &НачалоПериода

FAQ: Частые вопросы по конструкции ГДЕ

Можно ли в условии ГДЕ использовать функции работы со строками, например НАЙТИ()?

Да, можно, но это может негативно сказаться на производительности, так как функции над полями обычно не используют индексы. Например, условие ГДЕ НАЙТИ(Наименование, "АБВ") > 0 приведёт к полному сканированию таблицы. Лучше использовать ПОДОБНО или полнотекстовый поиск, если он настроен.

Как отфильтровать данные по нескольким значениям одного поля без многократного повторения условия?

Используйте оператор В (аналог IN в SQL). Например:

ГДЕ

Контрагент В (&СписокКонтрагентов)

где &СписокКонтрагентов — это массив или список значений. Это намного эффективнее, чем перечислять условия через ИЛИ.

Почему запрос с условием ГДЕ ПометкаУдаления = ЛОЖЬ возвращает удалённые документы?

Это происходит из-за особенностей платформы 1С. Поле ПометкаУдаления может не обновляться мгновенно при программном удалении объектов. Чтобы гарантированно исключить помеченные на удаление объекты, используйте системное поле Ссылка.ПометкаУдаления или проверяйте статус через метод ЭтоГруппа() для справочников.

Как в условии ГДЕ проверить, что поле содержит одно из нескольких возможных значений перечисления?

Используйте оператор В с явным указанием значений перечисления через функцию ЗНАЧЕНИЕ(). Пример:

ГДЕ

Статус В (

ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Оплачен),

ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Отгружен)

)

Не сравнивайте перечисления со строками — это приведёт к ошибке.

Можно ли в условии ГДЕ использовать подзапрос, который возвращает несколько строк?

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

💡

Если вам нужно отладить сложный запрос с множеством условий в ГДЕ, попробуйте временно закомментировать часть условий (с помощью / /) и проверять результаты пошагово. Это поможет локализовать ошибку.