Работа с данными в платформе 1С:Предприятие 8 невозможно представить без использования встроенного языка запросов. Ключевым элементом, позволяющим отфильтровать необходимые записи из огромных массивов информации, является оператор ГДЕ. Именно он определяет, какие строки попадут в результат выборки, а какие будут отброшены еще на уровне СУБД, что критически важно для производительности системы.

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

Базовый синтаксис и место в структуре запроса

Оператор ГДЕ всегда располагается после предложения ИЗ и перед возможными операторами СГРУППИРОВАТЬ ПО, ИМЕЮЩИЕ или УПОРЯДОЧИТЬ ПО. Он служит фильтром, который применяется к каждой строке результирующего набора данных таблицы или временной таблицы. Если условие истинно, строка включается в выборку.

Синтаксически условие представляет собой логическое выражение, возвращающее булевское значение. Вы можете использовать различные операторы сравнения, такие как =, <>, <, >, а также логические связки И, ИЛИ, НЕ. Важно помнить о приоритете операций: скобки позволяют явно задавать порядок вычисления сложных условий.

Рассмотрим простейший пример выборки номенклатуры с определенным видом. Здесь мы обращаемся к полю справочника и сравниваем его с константой.

ВЫБРАТЬ

Номенклатура.Ссылка,

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

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

ИЗ

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

ГДЕ

Номенклатура.ВидНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар)

Обратите внимание, что для сравнения с перечислениями или константами метаданных часто используется функция ЗНАЧЕНИЕ(). Это гарантирует, что запрос останется рабочим даже при изменении внутренних идентификаторов объектов конфигурации. Использование литералов напрямую возможно, но менее надежно при рефакторинге.

⚠️ Внимание: Оператор ГДЕ фильтрует строки до агрегации. Если вам нужно отфильтровать результат после группировки (например, отобрать товары с суммой продаж более 1 млн), необходимо использовать оператор ИМЕЮЩИЕ, а не ГДЕ.

💡

Используйте псевдонимы таблиц (КАК TableName) для упрощения написания условий. Это делает код чище и легче читается, особенно при работе с длинными именами полей.

Работа с логическими операторами и приоритетами

При построении сложных условий фильтрации часто возникает необходимость комбинировать несколько критериев. Здесь на помощь приходят логические операторы. Правильное понимание их приоритета — залог корректной работы запроса. Оператор НЕ имеет наивысший приоритет, затем следует И, и самым низким приоритетом обладает ИЛИ.

Частой ошибкой новичков является отсутствие скобок при смешивании И и ИЛИ. Без явного указания группировки система может интерпретировать условие иначе, чем задумывал разработчик. Всегда используйте скобки для явного разделения логических блоков, даже если вам кажется, что приоритет очевиден.

Ниже приведен пример, где мы отбираем документы, проведенные в текущем месяце, но только если они относятся к определенному контрагенту или имеют конкретный статус.

ВЫБРАТЬ

Документ.РеализацияТоваровУслуг.Ссылка,

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

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

ИЗ

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

ГДЕ

(Документ.Контрагент = &Контрагент ИЛИ Документ.Статус = &Статус)

И Документ.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца

В данном случае скобки гарантируют, что условие по дате применится ко всей группе альтернативных условий по контрагенту и статусу. Без них запрос мог бы выбрать все документы за месяц независимо от контрагента, если бы выполнялось только условие по статусу.

  • 🔍 Используйте И для сужения выборки: все условия должны быть истинны.
  • 🔍 Используйте ИЛИ для расширения выборки: достаточно истинности хотя бы одного условия.
  • 🔍 Применяйте НЕ для исключения записей, не соответствующих критерию.

Сравнение с неопределенными значениями (NULL)

В языке запросов 1С существует специальное понятие ЕСТЬ NULL. Это критически важный аспект, так как обычное сравнение на равенство (=) с неопределенным значением всегда возвращает ЛОЖЬ. То есть, выражение Поле = NULL никогда не сработает, даже если поле действительно пустое.

Для проверки на заполненность или пустоту значения необходимо использовать специальные конструкции ЕСТЬ NULL и НЕ ЕСТЬ NULL. Это позволяет корректно обрабатывать ситуации, когда в базе данных отсутствуют данные в определенных полях, что часто встречается в регистрах сведений или документах с необязательными реквизитами.

Пример выборки сотрудников, у которых не указан телефон:

ВЫБРАТЬ

Сотрудники.Ссылка,

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

ИЗ

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

ГДЕ

Сотрудники.Телефон НЕ ЕСТЬ NULL

Почему NULL не равен NULL?

В теории баз данных NULL означает отсутствие значения. Сравнение "отсутствие" с "отсутствием" не дает истины, так как неизвестно, равны ли эти неизвестные величины. Поэтому используется специальный оператор.

Также стоит учитывать поведение составных типов. Если поле может хранить разные типы данных, проверка на NULL сработает только если значение действительно не определено, а не если там хранится пустая строка или ноль. Пустая строка "" и NULL — это разные сущности в контексте запросов.

⚠️ Внимание: При использовании внешних источников данных или объединении запросов, убедитесь, что типы полей совместимы. Сравнение строки с числом или датой может привести к неявным преобразованиям, которые иногда работают не так, как ожидается.

Использование параметров в условиях ГДЕ

Одним из главных преимуществ языка запросов 1С является параметризация. Вместо подстановки значений прямо в текст запроса (что опасно и неэффективно), мы используем параметры, начинающиеся с символа амперсанда &. Это позволяет системе 1С кэшировать план выполнения запроса, что значительно ускоряет работу при многократном вызове одного и того же кода с разными данными.

Параметры передаются в метод Выполнить() объекта запроса через коллекцию Параметры. Тип значения параметра должен соответствовать типу поля, с которым он сравнивается, либо быть универсальным (например, Строка), чтобы СУБД могла выполнить приведение типов. Однако лучше избегать неявных приведений для сохранения производительности.

Рассмотрим пример универсального отчета, где пользователь может выбрать период и организацию:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РегистрНакопления.Продажи.Период,

| РегистрНакопления.Продажи.Организация,

| СУММА(РегистрНакопления.Продажи.Сумма) КАК Сумма

|ИЗ

| РегистрНакопления.Продажи КАК Продажи

|ГДЕ

| Продажи.Период МЕЖДУ &НачПериода И &КонПериода

| И Продажи.Организация = &Организация

|

|СГРУППИРОВАТЬ ПО

| Продажи.Период,

| Продажи.Организация";

Запрос.УстановитьПараметр("НачПериода", НачалоПериода);

Запрос.УстановитьПараметр("КонПериода", КонецПериода);

Запрос.УстановитьПараметр("Организация", ВыбраннаяОрганизация);

Использование параметров также защищает от SQL-инъекций (хотя в 1С это менее актуально, чем в веб-разработке, принцип остается важным для безопасности и целостности данных). Кроме того, это упрощает отладку: вы можете менять значения параметров в отладчике, не переписывая текст запроса.

📊 Как вы чаще всего передаете параметры в запрос?
Через УстановитьПараметр
Через структуру параметров
Через константы в тексте
Использую Глобальные переменные

Оптимизация и использование индексов

Эффективность выполнения запроса напрямую зависит от того, как построено условие в блоке ГДЕ. СУБД использует индексы для быстрого поиска записей. Однако индекс может быть использован только если условие сформулировано определенным образом. Главная задача разработчика — писать условия так, чтобы они были SARGable (Search ARGument Able).

Критическое правило: никогда не применяйте функции к полям таблицы в левой части оператора сравнения. Если вы напишете ГОД(Документ.Дата) = 2026, система будет вынуждена просканировать каждую строку таблицы, вычисляя функцию, что убьет производительность на больших объемах. Индекс по полю Дата в этом случае не сработает.

Вместо этого используйте диапазоны значений. То же самое условие следует переписать через оператор МЕЖДУ или сравнения >= и <. Это позволит движку 1С и СУБД сразу перейти к нужному участку индекса.

Плохой вариант (медленно) Хороший вариант (быстро) Причина
ЛЕВЫЙ(Номер, 2) = "АВ" Номер МЕЖДУ "АВ..." И "АВ~" Функция над полем блокирует индекс
ГОД(Дата) = 2026 Дата МЕЖДУ "20260101" И "20261231" Полное сканирование таблицы
СУММА(Поле) > 100 Поле > 100 (в ГДЕ) Агрегатные функции в ГДЕ запрещены

Также стоит избегать условий с оператором ИЛИ, если они затрагивают разные поля, по которым существуют отдельные индексы. В таких случаях СУБД может выбрать только один индекс и отфильтровать остальные строки вручную. Иногда эффективнее разбить такой запрос на два отдельных запроса и объединить их через ОБЪЕДИНИТЬ ВСЕ.

⚠️ Внимание: Конфигурация 1С и версия платформы постоянно обновляются. Оптимизатор запросов совершенствуется, и то, что было медленно в версии 8.3.10, может работать быстро в 8.3.24. Всегда проверяйте производительность через консоль запросов или технологический журнал на актуальной версии платформы.

☑️ Чек-лист оптимизации условия ГДЕ

Выполнено: 0 / 5

Частые ошибки и способы их устранения

При написании запросов разработчики часто сталкиваются с типовыми проблемами, которые приводят к ошибкам выполнения или неверным результатам. Одна из самых распространенных — попытка использовать агрегатные функции (СУММА, КОЛИЧЕСТВО, МИНИМУМ) непосредственно в условии ГДЕ. Это синтаксически запрещено, так как фильтрация происходит до группировки.

Другая частая ошибка — несовпадение типов данных. Если вы пытаетесь сравнить строковое поле с числовым параметром без явного приведения, запрос может завершиться ошибкой "Тип значения не соответствует типу поля". В таких случаях используйте функцию ЕСТЬNULL для подстановки значений или явно приводите типы, хотя последнее в 1С делается автоматически не всегда корректно.

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

  • Ошибка: Использование СУММА(Поле) > 100 в блоке ГДЕ.
    Решение: Перенести условие в блок ИМЕЮЩИЕ после группировки.
  • Ошибка: Сравнение Дата = "20.10.2023" (строка).
    Решение: Использовать тип Дата: Дата = ДАТА(2023, 10, 20) или параметр.
  • Ошибка: Фильтрация по полям, не включенным в выборку, без индексов.
    Решение: Проверить настройки индексов в конфигураторе для используемых полей.
💡

Главное правило оптимизации: пишите условия так, чтобы СУБД могла использовать индексы. Избегайте функций над полями в левой части сравнения и используйте диапазоны вместо вычислений.

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

Да, язык запросов 1С поддерживает вложенные запросы. Вы можете использовать конструкцию ПОДЗАПРОС или просто вставить запрос в скобках после оператора В (IN). Например: ГДЕ Ссылка В (ВЫБРАТЬ Ссылка ИЗ ...). Это мощный инструмент для фильтрации по сложным наборам данных, но требует осторожности с производительностью.

В чем разница между ГДЕ и ИМЕЮЩИЕ?

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

Как проверить, используется ли индекс в моем запросе?

Для анализа плана выполнения запроса используйте консоль запросов в режиме предприятия или технологический журнал (ТЖ). В текстовом представлении плана выполнения ищите операции "Index Seek" или "Index Scan". Если видите "Table Scan" на больших таблицах, значит, индекс не используется, и условие в ГДЕ написано неоптимально.

Что делать, если условие ГДЕ возвращает пустой результат, хотя данные есть?

Проверьте типы данных параметров и полей. Убедитесь, что нет лишних пробелов в строках (используйте СОКРЛ и СОКРП при необходимости, но лучше на этапе записи). Проверьте логику соединений (ЛЕВОЕ СОЕДИНЕНИЕ может давать NULL, которые отсекаются простым условием равенства). Также проверьте права доступа пользователя к данным.