К статье
Практический материал

Разработка и Конфигурация · 9 мин

ИМЕЮЩИЕ и ГДЕ в запросе 1С: отличия, синтаксис и примеры

Чем отличается ИМЕЮЩИЕ от ГДЕ в запросах 1С, как фильтровать сгруппированные данные, типичные ошибки и готовые примеры запросов с пояснениями.

В языке запросов 1С есть две конструкции для отбора данных: ГДЕ и ИМЕЮЩИЕ. Первая фильтрует строки до группировки, вторая — уже сгруппированные результаты после неё. Путаница между ними — одна из самых частых причин ошибок «Поле не найдено» и неверных итогов в отчётах.

Конструкция ГДЕ работает с полями исходных таблиц: документов, регистров, справочников. Конструкция ИМЕЮЩИЕ работает только с агрегатными функциями — СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ. Если нужно отобрать контрагентов, у которых сумма продаж больше заданной, — это задача для ИМЕЮЩИЕ, а не для ГДЕ.

Ниже разобран синтаксис обеих конструкций, порядок их выполнения, готовые примеры запросов и типичные ошибки разработчиков при работе с группировками.

Что делает конструкция ГДЕ и когда её применять

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

ВЫБРАТЬ

Продажи.Номенклатура КАК Номенклатура,

Продажи.Количество КАК Количество

ИЗ

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

ГДЕ

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

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

Типичные условия в ГДЕ: сравнение с параметром, проверка В / В ИЕРАРХИИ, ПОДОБНО для строк, МЕЖДУ для диапазонов, проверка на NULL через ЕСТЬ NULL. Все эти отборы сокращают объём данных ещё до агрегации, что положительно сказывается на скорости запроса.

Что делает конструкция ИМЕЮЩИЕ

Секция ИМЕЮЩИЕ применяется к результату группировки и позволяет отбрасывать целые группы по значениям агрегатных функций. Пример задачи: показать только тех клиентов, чья сумма закупок превышает 100 000, или товары, которые продавались более 5 раз.

ВЫБРАТЬ

Продажи.Контрагент КАК Контрагент,

СУММА(Продажи.СуммаОборот) КАК СуммаПродаж

ИЗ

РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

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

Продажи.Контрагент

ИМЕЮЩИЕ

СУММА(Продажи.СуммаОборот) > 100000

Обратите внимание: в ИМЕЮЩИЕ агрегатная функция пишется заново, а не по псевдониму поля. Запись ИМЕЮЩИЕ СуммаПродаж > 100000 в некоторых случаях сработает, но надёжнее и понятнее повторять саму агрегатную функцию — так запрос однозначно читается и конструктор запроса не переиначит условие.

В ИМЕЮЩИЕ можно комбинировать несколько условий через И, ИЛИ, использовать КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) и другие агрегаты, даже если они не выведены в список выборки.

Порядок выполнения секций запроса

Понимание последовательности обработки устраняет большинство ошибок. Логический порядок такой:

  1. ИЗ — выбираются источники и соединения таблиц.
  2. ГДЕ — строки фильтруются по условиям.
  3. СГРУППИРОВАТЬ ПО — оставшиеся строки собираются в группы.
  4. ИМЕЮЩИЕ — группы фильтруются по агрегатам.
  5. УПОРЯДОЧИТЬ ПО — результат сортируется.

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

Как построить запрос с ИМЕЮЩИЕ
  1. 1
    Сформулируйте условие: фильтруется строка или группа. Если в условии участвует СУММА или КОЛИЧЕСТВО — это ИМЕЮЩИЕ.
  2. 2
    Напишите выборку с СГРУППИРОВАТЬ ПО по нужным измерениям.
  3. 3
    Добавьте ГДЕ для предварительного отбора строк (период, организация, склад).
  4. 4
    Добавьте ИМЕЮЩИЕ с агрегатной функцией после секции группировки.
  5. 5
    Выполните запрос в консоли запросов и сверьте количество строк с ожидаемым.

Примеры: ГДЕ и ИМЕЮЩИЕ в одном запросе

Отбор товаров с большим суммарным остатком

Задача: найти номенклатуру, суммарный остаток которой по всем складам превышает 1000 единиц, при этом учитывать только активные склады.

ВЫБРАТЬ

Остатки.Номенклатура КАК Номенклатура,

СУММА(Остатки.КоличествоОстаток) КАК ОбщийОстаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(, ) КАК Остатки

ГДЕ

НЕ Остатки.Склад.ПометкаУдаления

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

Остатки.Номенклатура

ИМЕЮЩИЕ

СУММА(Остатки.КоличествоОстаток) > 1000

Здесь ГДЕ отсекает помеченные на удаление склады до группировки, а ИМЕЮЩИЕ убирает группы с малым итогом. Перенести условие по сумме в ГДЕ нельзя — агрегат там недоступен.

Дубли по количеству документов

Задача: найти контрагентов, на которых за период оформлено более 10 заказов.

ВЫБРАТЬ

Заказ.Контрагент КАК Контрагент,

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Заказ.Ссылка) КАК ЧислоЗаказов

ИЗ

Документ.ЗаказКлиента КАК Заказ

ГДЕ

Заказ.Проведен

И Заказ.Дата МЕЖДУ &Начало И &Конец

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

Заказ.Контрагент

ИМЕЮЩИЕ

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Заказ.Ссылка) > 10

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

Первая ошибка — попытка написать ГДЕ СУММА(...) > 0. Запрос не выполнится: агрегатные функции в ГДЕ запрещены. Вторая — ссылка в ИМЕЮЩИЕ на неагрегатное поле, не входящее в группировку: такое поле не определено на уровне группы, и запрос вернёт ошибку.

Третья ошибка — обратная: разработчик фильтрует в ИМЕЮЩИЕ то, что можно было отфильтровать в ГДЕ, например ИМЕЮЩИЕ МАКСИМУМ(Продажи.Организация) = &Организация. Запрос сработает, но заставит СУБД сгруппировать лишние данные. Условие по организации правильно разместить в ГДЕ или в параметрах виртуальной таблицы.

Типичные ошибки
01
Агрегатная функция в секции ГДЕ — запрос не выполнится, условие по СУММА/КОЛИЧЕСТВО переносится в ИМЕЮЩИЕ.
02
Отбор по обычному полю через ИМЕЮЩИЕ вместо ГДЕ — лишняя группировка всех данных и замедление запроса.
03
Ссылка в ИМЕЮЩИЕ на поле, которого нет ни в группировке, ни в агрегате — ошибка «поле не найдено».
04
Условия по периоду в ГДЕ вместо параметров виртуальной таблицы Обороты/Остатки — потеря производительности.

ИМЕЮЩИЕ без явной группировки

Менее известный приём: ИМЕЮЩИЕ допустимо и без секции СГРУППИРОВАТЬ ПО. Тогда весь результат считается одной группой, и условие либо пропускает её, либо возвращает пустой результат. Это удобно для проверок вида «есть ли в базе хотя бы один документ с суммой больше N».

ВЫБРАТЬ

СУММА(Продажи.СуммаОборот) КАК Итого

ИЗ

РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

ИМЕЮЩИЕ

СУММА(Продажи.СуммаОборот) > &Порог

Если сумма за период не превысила порог, запрос вернёт ноль строк — это можно использовать в коде как логическое условие через Результат.Пустой().

ГДЕ или ИМЕЮЩИЕ

ГДЕ

Условия по полям таблиц: период, организация, контрагент. Выполняется до группировки, ускоряет запрос. Агрегаты запрещены.

ИМЕЮЩИЕ

Условия по итогам групп: сумма, количество, максимум. Работает только после группировки или с неявной группировкой всего результата.

Параметры виртуальной таблицы

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

Как проверить корректность запроса

Перед запуском в рабочей базе проверьте запрос в консоли запросов на копии или на тестовом периоде. Сравните количество строк результата с контрольным отчётом: например, сверьте список контрагентов из запроса с отбором по сумме с аналогичным отбором в типовом отчёте «Продажи».

Полезный приём — временно убрать секцию ИМЕЮЩИЕ и посмотреть полный сгруппированный результат. Так видно, какие группы отсекает условие, и легко заметить ошибку в пороге или знаке сравнения.

Контрольные точки

Как проверить результат

Количество строк результата
Норма

Совпадает с контрольным отчётом или ручным подсчётом по выборке

Тревожный признак

Строк меньше ожидаемого — проверьте знак сравнения и порог в ИМЕЮЩИЕ

Итоговые суммы
Норма

Суммы по группам соответствуют данным регистра за период

Тревожный признак

Суммы завышены — возможно, условие ГДЕ не отсекло лишние строки до группировки

Время выполнения
Норма

Запрос выполняется за секунды на рабочем объёме данных

Тревожный признак

Запрос «виснет» — условия по обычным полям ошибочно перенесены в ИМЕЮЩИЕ

FAQ

Можно ли использовать ГДЕ и ИМЕЮЩИЕ в одном запросе?

Да, это нормальная практика. ГДЕ размещается до СГРУППИРОВАТЬ ПО и фильтрует строки, ИМЕЮЩИЕ — после группировки и фильтрует группы по агрегатным функциям.

Почему запрос с СУММА в секции ГДЕ выдаёт ошибку?

Агрегатные функции вычисляются только после группировки, а ГДЕ выполняется раньше. Перенесите условие с СУММА, КОЛИЧЕСТВО, МАКСИМУМ в секцию ИМЕЮЩИЕ.

Можно ли в ИМЕЮЩИЕ ссылаться на псевдоним поля из ВЫБРАТЬ?

Технически платформа иногда принимает псевдоним, но надёжнее повторять саму агрегатную функцию: ИМЕЮЩИЕ СУММА(Продажи.Сумма) > 1000. Так запрос однозначен и не ломается при правке в конструкторе.

Что быстрее: отбор в ГДЕ или в ИМЕЮЩИЕ?

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

Работает ли ИМЕЮЩИЕ без СГРУППИРОВАТЬ ПО?

Да. Весь результат трактуется как одна группа: если условие выполняется, возвращается одна строка с итогом, иначе — пустой результат. Это удобно для проверок пороговых значений в коде.

Как отобрать группы, где количество различных значений больше заданного?

Используйте КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) в ИМЕЮЩИЕ, например: ИМЕЮЩИЕ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Заказ.Номенклатура) > 5 — так отбираются документы или контрагенты с более чем пятью разными позициями.

Итог

Что важно запомнить

ГДЕ фильтрует строки до группировки по обычным полям, ИМЕЮЩИЕ — группы после группировки по агрегатным функциям. Всё, что можно отобрать заранее, выносите в ГДЕ или параметры виртуальных таблиц, а ИМЕЮЩИЕ оставьте для условий по СУММА, КОЛИЧЕСТВО и другим итогам.