При работе с запросами в системе 1С:Предприятие часто возникает задача отфильтровать данные не по конкретным значениям полей, а по результатам вычислений — например, найти записи, у которых количество различных реквизитов больше одного (поиск дублей) или, наоборот, строго равно единице. В этой статье мы подробно разберем, почему стандартное условие ГДЕ здесь не поможет, как правильно использовать секцию ИМЕЮЩИЕ и как извлечь конкретное значение из сгруппированного результата.
Рассмотрим типичную ошибку начинающего разработчика. Попытка написать условие ГДЕ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т.Реквизит) > 1 приведет к ошибке синтаксиса. Проанализируем причину: секция ГДЕ (в SQL — WHERE) применяется к каждой отдельной строке исходной таблицы до того, как начнется процесс группировки. Поскольку агрегатная функция (такая как СУММА или КОЛИЧЕСТВО) вычисляется только для группы строк, система не может применить это условие на этапе предварительного отбора.
Для решения этой задачи в языке запросов предусмотрена специальная секция ИМЕЮЩИЕ (в SQL — HAVING). Она работает с результатами, которые уже прошли стадию группировки и вычисления всех агрегатов.
Разберем конкретный пример. Нам нужно найти комбинации организации и измерения, для которых в регистре сведений указано более одного различного значения определенного реквизита. Напишем корректный текст запроса:
ВЫБРАТЬ
Т.Организация КАК Организация,
Т.Измерение КАК Измерение,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т.Реквизит) КАК КоличествоРеквизитов
ИЗ
РегистрСведений.Т КАК Т
СГРУППИРОВАТЬ ПО
Т.Организация,
Т.Измерение
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т.Реквизит) > 1
В данном примере мы сначала группируем записи по ключевым полям, а затем отсекаем те группы, внутри которых Реквизит принимает только одно уникальное значение или вовсе пуст.
Иногда задача усложняется: нам нужно не просто убедиться, что количество различных значений равно 1, но и вывести это самое значение в отчет. Если мы просто добавим поле Реквизит в секцию ВЫБРАТЬ, нам придется добавить его и в СГРУППИРОВАТЬ ПО. Однако в этом случае группировка произойдет по самому реквизиту, и количество различных значений в каждой группе всегда будет равно единице, что сделает условие ИМЕЮЩИЕ бессмысленным.
Рассмотрим правильный подход: использование функций МАКСИМУМ или МИНИМУМ. Когда мы через ИМЕЮЩИЕ установили, что различных значений ровно одно, функции МАКСИМУМ и МИНИМУМ вернут одно и то же — то самое единственное значение.
Пример запроса для получения уникального наименования:
ВЫБРАТЬ
ВТ.Организация КАК Организация,
МАКСИМУМ(ВТ.Реквизит) КАК СамоЗначение
ИЗ
ВТ КАК ВТ
СГРУППИРОВАТЬ ПО
ВТ.Организация
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ.Реквизит) = 1
Этот прием позволяет нам получить данные из колонки, не «разваливая» группировку по основному полю.
Выясним причину, по которой запросы с КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) могут работать медленно на больших объемах данных (сотни тысяч и миллионы строк). Для выполнения этой операции СУБД вынуждена создавать временные структуры данных в оперативной памяти или в базе tempdb для сортировки и отсеивания дублей внутри каждой группы.
Рекомендации по оптимизации:
РАЗЛИЧНЫЕ).Организация, Измерение) и в подсчете (Реквизит), входят в состав индексов. В регистрах сведений это, как правило, измерения.ВЫРАЗИТЬ(...) или предварительный фильтр в ГДЕ.Важно помнить критическое правило языка запросов 1С и SQL: агрегатная функция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) игнорирует значения NULL. Рассмотрим ситуацию: у вас есть три записи. В первой Реквизит = "Значение1", во второй и третьей — NULL. Функция вернет 1, так как NULL не считается значением для сравнения.
Если для вашей бизнес-логики NULL (пустое значение) является значимым вариантом «различности», используйте функцию ЕСТЬNULL для замены неопределенности на конкретное значение-заглушку перед выполнением группировки.
Проанализируем пример с заменой NULL:
ВЫБРАТЬ
Т.Организация,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЕСТЬNULL(Т.Реквизит, "ПУСТО")) КАК КолВо
ИЗ
РегистрСведений.Т КАК Т
СГРУППИРОВАТЬ ПО
Т.Организация
В этом случае, если в данных есть хотя бы одна строка с NULL, она будет посчитана как отдельное уникальное состояние "ПУСТО".
Мы проанализировали основные аспекты фильтрации сгруппированных данных. Подведем итоги: для условий на агрегаты используем ИМЕЮЩИЕ, для извлечения единственного значения из группы — МАКСИМУМ, а при работе с большими таблицами уделяем внимание индексам и обработке NULL. Эти инструменты позволяют строить мощные аналитические отчеты и эффективно находить ошибки в данных конфигураций 1С.