Часто при работе с запросами в 1С возникает задача отфильтровать результат не по значению поля в каждой отдельной строке, а по итоговому, агрегированному значению после группировки. Например, найти все товары, которых продано больше 100 штук, или, как в нашем случае, найти элементы справочника с одинаковыми наименованиями, то есть дубли. Стандартный оператор ГДЕ здесь не поможет, так как он работает до группировки данных.
Давайте вместе разберемся, как правильно накладывать условия на итоговые данные в запросах 1С. Проанализируем ситуацию на классическом примере — поиске дублей в справочнике.
Прежде чем перейти к решениям, давайте выясним причину, почему нельзя просто написать условие в секции ГДЕ. В языке запросов 1С существует четкое разделение обязанностей между двумя операторами фильтрации:
СГРУППИРОВАТЬ ПО и к ним были применены агрегатные функции, такие как КОЛИЧЕСТВО(), СУММА(), СРЕДНЕЕ() и другие.Таким образом, для фильтрации по итогам нам нужен именно оператор ИМЕЮЩИЕ. Рассмотрим подробнее, как его использовать.
Это самый простой и быстрый способ, если наша цель — просто увидеть, какие наименования в справочнике повторяются и сколько раз. Нам не нужны ссылки на сами элементы, только информация о факте дублирования.
Разберем по шагам логику запроса:
Справочник.Справочник2).Наименование. В результате для каждого уникального наименования мы получим одну строку.КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Ссылка). Это даст нам число дублей для каждого наименования.ИМЕЮЩИЕ отбираем только те группы (наименования), у которых подсчитанное количество больше единицы. Это и будут наши дубли.Посмотрим на пример кода, который реализует эту логику:
ВЫБРАТЬ
Справочник2.Наименование КАК Наименование,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Справочник2.Ссылка) КАК КоличествоДублей
ИЗ
Справочник.Справочник2 КАК Справочник2
СГРУППИРОВАТЬ ПО
Справочник2.Наименование
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Справочник2.Ссылка) > 1
В результате выполнения этого запроса мы получим таблицу из двух колонок: Наименование и КоличествоДублей, где будут перечислены только те наименования, которые встречаются в справочнике более одного раза.
Чаще всего нам нужно не просто узнать о наличии дублей, а получить ссылки на конкретные повторяющиеся элементы, чтобы, например, обработать их или пометить на удаление. В этом случае задача усложняется, и решить ее одним запросом не получится. Здесь мы применим подход с использованием временных таблиц.
Алгоритм будет состоять из двух шагов:
Рассмотрим этот двухэтапный запрос подробнее:
ВЫБРАТЬ
Справочник2.Наименование КАК Наименование
ПОМЕСТИТЬ ВременнаяТаблицаДублиСправочников
ИЗ
Справочник.Справочник2 КАК Справочник2
СГРУППИРОВАТЬ ПО
Справочник2.Наименование
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) > 1
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Справочник2.Ссылка КАК Ссылка
ИЗ
Справочник.Справочник2 КАК Справочник2
ГДЕ
Справочник2.Наименование В (ВЫБРАТЬ
ВременнаяТаблицаДублиСправочников.Наименование
ИЗ
ВременнаяТаблицаДублиСправочников)
Проанализируем, что здесь происходит:
КОЛИЧЕСТВО(*) больше 1, и складывает их во временную таблицу с именем ВременнаяТаблицаДублиСправочников.Ссылка из исходного справочника. С помощью условия ГДЕ и вложенного запроса мы отбираем только те элементы, Наименование которых присутствует в нашей временной таблице.В результате мы получаем полный список ссылок на все элементы, у которых есть дубли по наименованию. Это самый надежный и универсальный способ для решения подобных задач.
← К списку