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