Работа с базой данных в 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С не всегда явно сообщает об ошибке при сравнении, например, строки и числа. Результат может быть неожиданным:
ГДЕ ЧисловоеПоле = '100' -- сработает, но неявно преобразует типы - Неучёт регистра в строках:
По умолчанию сравнение строк регистрозависимо. Используйте
ВРЕГ():ГДЕ ВРЕГ(Контрагент.Наименование) = ВРЕГ('иванов') - Избыточные условия:
Условия, которые дублируют логику соединений, например:
ГДЕ Товар.Ссылка = Документ.Товар -- избыточно, если это уже в ПО
Для диагностики ошибок используйте:
- 🔍
ОбъяснитьЗапрос()— покажет план выполнения. - 🔍 Конструктор запросов в конфигураторе — визуализирует связи.
- 🔍 Лог СУБД (если есть доступ) — для анализа медленных запросов.
Что делать, если запрос с ГДЕ работает слишком долго?
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
Это позволит СУБД использовать индексы для каждого условия отдельно.