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

Вы узнаете, как правильно комбинировать операторы (=, >, В, ПОДОБНО), избегать типичных ловушек при работе с датами и ссылками, а также научитесь диагностировать распространённые ошибки вроде «Неопределённое поведение при сравнении с NULL». Материал будет полезен и новичкам, и опытным разработчикам, которые хотят систематизировать знания или найти решение для специфической задачи.

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

📊 Как часто вы используете сложные условия ГДЕ в запросах 1С?
Ежедневно
Несколько раз в неделю
Редко, только при необходимости
Предпочитаю обрабатывать данные после выборки

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

Конструкция ГДЕ в языке запросов аналогична WHERE в SQL, но имеет свои синтаксические особенности. Она размещается после описания полей выборки (ВЫБРАТЬ) и перед группировкой (СГРУППИРОВАТЬ ПО). Основная структура:

ВЫБРАТЬ

Поле1, Поле2

ИЗ

Таблица1 КАК Т1

ГДЕ

Т1.Поле1 = Значение1

И Т1.Поле2 > Значение2

Ключевые правила:

  • 🔹 Условия пишутся после ключевого слова ГДЕ, каждое с новой строки (рекомендуется для читаемости).
  • 🔹 Операторы сравнения: =, <>, >, <, >=, <=.
  • 🔹 Логические операторы: И (AND), ИЛИ (OR), НЕ (NOT).
  • 🔹 Для строковых значений используйте одинарные кавычки: ГДЕ Наименование = 'Товар1'.

Пример с несколькими условиями:

ВЫБРАТЬ

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

ДокументОприходования.Дата

ИЗ

Документ.ОприходованиеТоваров КАК ДокументОприходования

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

ПО ДокументОприходования.Номенклатура = Номенклатура.Ссылка

ГДЕ

ДокументОприходования.Дата >= &НачалоПериода

И ДокументОприходования.Дата <= &КонецПериода

И Номенклатура.ВидыНоменклатуры = &ВидНоменклатуры

⚠️ Внимание: В версиях 1С ниже 8.3.18 оператор НЕ в условиях ГДЕ мог приводить к неоптимальным планам выполнения. Для старых конфигураций проверяйте производительность таких запросов.

2. Операторы для работы со строками и датами

Фильтрация текстовых полей и дат требует особого подхода. Для строк доступны операторы ПОДОБНО (LIKE), НАЧИНАЕТСЯ С, а для дат — функции вроде НАЧАЛОПЕРИОДА().

Примеры:

  • 📌 Поиск по подстроке: ГДЕ Контрагент.Наименование ПОДОБНО '%ООО%'.
  • 📅 Даты в диапазоне: ГДЕ Документ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания.
  • 🗓️ Текущий месяц: ГДЕ Документ.Дата >= НАЧАЛОМЕСЯЦА(&ТекущаяДата).

Важный нюанс: при сравнении дат без времени (ДАТАВРЕМЯ(2023,1,1)) условие = сработает только для записей с временем 00:00:00. Для корректной фильтрации используйте:

ГДЕ Документ.Дата >= НАЧАЛОДНЯ(&Дата)

И Документ.Дата < КОНЕЦДНЯ(&Дата)

Оператор Пример Аналог в SQL
ПОДОБНО '%текст%' LIKE
В ГДЕ Поле В (&МассивЗначений) IN
МЕЖДУ ГДЕ Дата МЕЖДУ Д1 И Д2 BETWEEN
💡

Для ускорения запросов с ПОДОБНО создавайте функциональные индексы на текстовые поля или используйте полнотекстовый поиск, если он поддерживается СУБД.

3. Работа с NULL и пустыми ссылками

Одна из самых распространённых ошибок — некорректная обработка NULL-значений (в 1С это NULL для полей базы данных и Неопределено для ссылочных типов). Операторы сравнения с NULL всегда возвращают ЛОЖЬ, поэтому для проверки на пустоту используйте:

ГДЕ Поле ЕСТЬ NULL  -- для полей БД

ГДЕ Ссылка.Поле ЕСТЬ NULL -- для ссылочных полей

Примеры проблемных конструкций:

  • ГДЕ Поле = NULL → всегда ЛОЖЬ.
  • ГДЕ НЕ (Поле = Значение) → не учитывает NULL.
  • ГДЕ Поле <> Значение ИЛИ Поле ЕСТЬ NULL → корректная альтернатива.

Для ссылочных полей (например, справочников) используйте:

ГДЕ Номенклатура.Ссылка ЕСТЬ NULL  -- пустая ссылка

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

⚠️ Внимание: В платформе 1С 8.3.20+ изменилось поведение оператора В при работе с NULL. Теперь конструкция ГДЕ Поле В (Значение1, NULL) корректно обрабатывает пустые значения, тогда как в старых версиях это приводило к ошибкам.

4. Сложные условия: подзапросы и соединения

Условия в ГДЕ могут включать подзапросы или ссылки на поля из соединённых таблиц. Это мощный инструмент, но требует аккуратности при написании.

Пример с подзапросом:

ВЫБРАТЬ

Товар.Наименование

ИЗ

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

ГДЕ

Товар.Ссылка В (

ВЫБРАТЬ

ТоварыВЗаказе.Номенклатура

ИЗ

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

ГДЕ

ТоварыВЗаказе.Заказ.Дата >= &ДатаНачала

)

При соединении таблиц условия можно размещать:

  • 🔗 В самом соединении (ПО): фильтрация происходит до соединения (эффективнее).
  • 🔗 В разделе ГДЕ: фильтрация после соединения.

Сравнение производительности:

-- Вариант 1: условие в ПО (быстрее)

ЛЕВОЕ СОЕДИНЕНИЕ Документ.Реализация КАК Реализация

ПО Реализация.Контрагент = Контрагент.Ссылка

И Реализация.Дата >= &ДатаНачала

-- Вариант 2: условие в ГДЕ (медленнее)

ЛЕВОЕ СОЕДИНЕНИЕ Документ.Реализация КАК Реализация

ПО Реализация.Контрагент = Контрагент.Ссылка

ГДЕ

Реализация.Дата >= &ДатаНачала

1. Убедиться, что все поля из подзапроса существуют в основной выборке

2. Проверить логику операторов (И/ИЛИ) на приоритетность

3. Оценить объём данных — возможно, лучше разбить на несколько запросов

4. Протестировать на небольшой выборке-->

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

Даже опытные разработчики допускают ошибки при работе с условиями ГДЕ. Вот самые распространённые:

  1. Сравнение разных типов данных:

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

    ГДЕ ЧисловоеПоле = '100'  -- сработает, но неявно преобразует типы
  2. Неучёт регистра в строках:

    По умолчанию сравнение строк регистрозависимо. Используйте ВРЕГ():

    ГДЕ ВРЕГ(Контрагент.Наименование) = ВРЕГ('иванов')
  3. Избыточные условия:

    Условия, которые дублируют логику соединений, например:

    ГДЕ Товар.Ссылка = Документ.Товар  -- избыточно, если это уже в ПО

Для диагностики ошибок используйте:

  • 🔍 ОбъяснитьЗапрос() — покажет план выполнения.
  • 🔍 Конструктор запросов в конфигураторе — визуализирует связи.
  • 🔍 Лог СУБД (если есть доступ) — для анализа медленных запросов.
Что делать, если запрос с ГДЕ работает слишком долго?

1. Проверьте наличие индексов на поля, используемые в условиях.

2. Разбейте сложный запрос на несколько простых с временными таблицами.

3. Замените подзапросы в ГДЕ на соединения (JOIN).

4. Используйте параметры (&Параметр) вместо констант — это позволяет 1С кэшировать планы выполнения.

6. Оптимизация условий ГДЕ

Производительность запросов с ГДЕ зависит от нескольких факторов:

1. Порядок условий:

СУБД обрабатывает условия слева направо, поэтому сначала размещайте те, которые отсекают больше строк:

-- Быстрее:

ГДЕ Дата >= &ДатаНачала -- отсекает 90% данных

И Контрагент = &Контрагент -- фильтрует оставшиеся 10%

-- Медленнее:

ГДЕ Контрагент = &Контрагент

И Дата >= &ДатаНачала

2. Использование функций в условиях:

Функции над полями (НАЧАЛОПЕРИОДА(), ВРЕГ()) препятствуют использованию индексов. Переносите их в параметры:

-- Плохо (индекс не используется):

ГДЕ НАЧАЛОПЕРИОДА(Документ.Дата, 'МЕСЯЦ') = &Дата

-- Хорошо:

ГДЕ Документ.Дата >= &ДатаНачалаМесяца

И Документ.Дата < &ДатаОкончанияМесяца

3. Замена ИЛИ на ОБЪЕДИНИТЬ:

Условия с ИЛИ часто приводят к полному сканированию таблиц. Альтернатива:

-- Медленно:

ВЫБРАТЬ Поля

ГДЕ Условие1 ИЛИ Условие2

-- Быстрее:

ВЫБРАТЬ Поля ГДЕ Условие1

ОБЪЕДИНИТЬ

ВЫБРАТЬ Поля ГДЕ Условие2

💡

Для критичных по производительности запросов всегда тестируйте альтернативные формулировки условий. Разница в скорости может достигать сотен раз!

7. Практические примеры для разных задач

Рассмотрим реальные сценарии использования ГДЕ в типовых конфигурациях.

Пример 1: Выборка документов за период с фильтрацией по статусу

ВЫБРАТЬ

Заказ.Номер,

Заказ.Дата,

Заказ.СуммаДокумента

ИЗ

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

ГДЕ

Заказ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания

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

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

Пример 2: Поиск номенклатуры с остатками на складе

ВЫБРАТЬ

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

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

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки(

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

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

) КАК ОстаткиТоваров

ПО Номенклатура.Ссылка = ОстаткиТоваров.Номенклатура

ГДЕ

ОстаткиТоваров.КоличествоОстатков > 0

И Номенклатура.ЭтоГруппа = ЛОЖЬ

Пример 3: Фильтрация по dinamическому списку значений

ВЫБРАТЬ

Сотрудник.Наименование

ИЗ

Справочник.Сотрудники КАК Сотрудник

ГДЕ

Сотрудник.Подразделение В (

ВЫБРАТЬ

Элементы.Ссылка

ИЗ

Справочник.Подразделения КАК Элементы

ГДЕ

Элементы.Родитель = &РодительскоеПодразделение

)

FAQ: Частые вопросы по условиям ГДЕ в 1С

Как в условии ГДЕ сравнить поле с массивом значений?

Используйте оператор В:

ГДЕ Поле В (&МассивЗначений)

Где &МассивЗначений — параметр типа Массив. Для больших массивов (1000+ элементов) лучше использовать временные таблицы.

Почему условие с датой не возвращает записей за текущий день?

Скорее всего, вы используете = для сравнения с датой без времени. Правильный вариант:

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

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

Как написать условие для поля типа "Булево"?

Используйте ИСТИНА или ЛОЖЬ:

ГДЕ Поле = ИСТИНА

ГДЕ НЕ Поле -- эквивалентно "Поле = ЛОЖЬ"

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

Нет, агрегатные функции (СУММА(), МАКСИМУМ()) разрешены только в ВЫБРАТЬ или ИМЕЮЩИЕ. Для фильтрации по агрегатам используйте подзапросы:

ВЫБРАТЬ Контрагент

ИЗ Документ.Заказ

ГДЕ Контрагент В (

ВЫБРАТЬ Контрагент

ИЗ Документ.Заказ

ГРУППИРОВАТЬ ПО Контрагент

ИМЕЮЩИЕ СУММА(СуммаДокумента) > 10000

)

Как оптимизировать запрос с множеством условий ИЛИ?

Замените ИЛИ на ОБЪЕДИНИТЬ ВСЕ:

-- Вместо:

ГДЕ Условие1 ИЛИ Условие2 ИЛИ Условие3

-- Используйте:

ВЫБРАТЬ Поля ГДЕ Условие1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ Поля ГДЕ Условие2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ Поля ГДЕ Условие3

Это позволит СУБД использовать индексы для каждого условия отдельно.