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

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

Как выбрать дубли в запросе 1С: практическое руководство

Как найти и выбрать дубли в запросе 1С: группировка с HAVING, соединение таблицы с самой собой, поиск дублей в справочниках и регистрах. Примеры кода и ошибки.

Дубли в данных 1С — типовая проблема: дважды заведённые контрагенты, повторяющиеся номенклатурные позиции, задвоенные записи в регистрах сведений. Прежде чем что-то удалять или объединять, дубли нужно корректно найти, и язык запросов 1С даёт для этого несколько рабочих инструментов: группировку с условием ИМЕЮЩИЕ (HAVING), соединение таблицы с самой собой и вложенные запросы.

Выбор способа зависит от задачи. Если нужно просто получить список значений, которые встречаются более одного раза, достаточно группировки с агрегатной функцией КОЛИЧЕСТВО. Если требуется вывести сами записи-дубли со всеми реквизитами — понадобится соединение результата группировки с исходной таблицей. Для поиска «похожих», но не идентичных значений (например, наименований с разным регистром букв) запрос придётся дополнить функциями обработки строк.

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

Что считать дублем и какие поля брать в ключ

Прежде чем писать запрос, определите критерий дублирования. Для справочника «Контрагенты» дублем обычно считается совпадение ИНН и КПП, для «Номенклатуры» — совпадение наименования и артикула, для регистра сведений — совпадение измерений. От выбранного набора полей зависит, какие поля попадут в секцию СГРУППИРОВАТЬ ПО.

Важно понимать: ссылка элемента уникальна всегда, поэтому группировать по ссылке бессмысленно — дублей не будет никогда. Группировать нужно по «смысловым» реквизитам: ИНН, наименованию, номеру документа вместе с датой и организацией. Часто в ключ включают несколько полей сразу, чтобы отсечь случайные совпадения.

Базовый способ: СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ

Конструкция ИМЕЮЩИЕ — аналог HAVING в SQL. Она накладывает условие на результат группировки, то есть на агрегатные значения, а не на отдельные строки. Именно это отличает её от секции ГДЕ, которая фильтрует записи до группировки.

Пример: найти ИНН, которые встречаются у нескольких контрагентов.

ВЫБРАТЬ

Контрагенты.ИНН КАК ИНН,

КОЛИЧЕСТВО(Контрагенты.Ссылка) КАК КоличествоЗаписей

ИЗ

Справочник.Контрагенты КАК Контрагенты

ГДЕ

Контрагенты.ИНН <> ""

И НЕ Контрагенты.ПометкаУдаления

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

Контрагенты.ИНН

ИМЕЮЩИЕ

КОЛИЧЕСТВО(Контрагенты.Ссылка) > 1

Обратите внимание на фильтр в секции ГДЕ: пустые ИНН исключены, иначе все элементы с незаполненным ИНН схлопнутся в одну гигантскую «группу дублей». Помеченные на удаление элементы тоже разумно исключить, если задача — почистить актуальные данные.

Группировать можно по нескольким полям. Например, дубли документов по номеру, дате и контрагенту:

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

Реализация.Номер,

НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ),

Реализация.Контрагент

ИМЕЮЩИЕ

КОЛИЧЕСТВО(*) > 1

Как получить сами записи-дубли, а не только ключи

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

ВЫБРАТЬ

Контрагенты.ИНН КАК ИНН

ПОМЕСТИТЬ ДублирующиесяИНН

ИЗ

Справочник.Контрагенты КАК Контрагенты

ГДЕ

Контрагенты.ИНН <> ""

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

Контрагенты.ИНН

ИМЕЮЩИЕ

КОЛИЧЕСТВО(*) > 1

;

ВЫБРАТЬ

Контрагенты.Ссылка КАК Ссылка,

Контрагенты.Наименование КАК Наименование,

Контрагенты.ИНН КАК ИНН

ИЗ

Справочник.Контрагенты КАК Контрагенты

ВНУТРЕННЕЕ СОЕДИНЕНИЕ ДублирующиесяИНН КАК Дубли

ПО Контрагенты.ИНН = Дубли.ИНН

УПОРЯДОЧИТЬ ПО

ИНН, Наименование

Внутреннее соединение оставит только те элементы, чей ИНН входит в список дублирующихся. Сортировка по ключу дубля группирует «пары» визуально — так результат удобнее проверять глазами.

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

Альтернатива: соединение таблицы с самой собой

Второй классический приём — самосоединение (self join). Таблица соединяется сама с собой по ключевому полю, а условие на неравенство ссылок отсекает совпадение записи с самой собой.

ВЫБРАТЬ РАЗЛИЧНЫЕ

Т1.Ссылка КАК Ссылка,

Т1.ИНН КАК ИНН

ИЗ

Справочник.Контрагенты КАК Т1

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Т2

ПО Т1.ИНН = Т2.ИНН

И Т1.Ссылка <> Т2.Ссылка

ГДЕ

Т1.ИНН <> ""

Без РАЗЛИЧНЫЕ каждая пара будет выведена дважды (А–Б и Б–А), а при трёх дублях — уже шесть строк. Этот способ нагляден, но на больших таблицах работает медленнее группировки: соединение порождает декартово произведение внутри каждой группы дублей.

Сравнение подходов

Группировка + ИМЕЮЩИЕ

Быстрее на больших объёмах, сразу даёт счётчик дублей. Не возвращает сами записи — нужно соединение с исходной таблицей.

Самосоединение

Сразу возвращает записи-дубли, удобно для попарного сравнения. Медленнее и требует РАЗЛИЧНЫЕ, иначе строки задваиваются.

Вложенный запрос в ГДЕ ... В (...)

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

Поиск «похожих» значений и учёт регистра

Точное совпадение не находит дубли вида «ООО Ромашка» и «ООО Ромашка» (двойной пробел) или «ромашка» в другом регистре. Для таких случаев значения приводят к каноническому виду прямо в запросе: убирают лишние пробелы и приводят регистр функциями ВРЕГ или НРЕГ.

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

ВРЕГ(СОКРЛП(Контрагенты.Наименование))

ИМЕЮЩИЕ

КОЛИЧЕСТВО(*) > 1

Учтите ограничение: СОКРЛП убирает пробелы только по краям строки, двойные пробелы внутри в запросе не схлопнуть — для этого потребуется предварительная обработка данных в коде. Если наименование — строка неограниченной длины, группировать по ней напрямую нельзя: сначала приведите её к ограниченной длине через ВЫРАЗИТЬ(... КАК СТРОКА(150)).

Дубли в регистрах сведений и накопления

В периодических регистрах сведений дубль — это несколько записей с одинаковым набором «период + измерения». Запрос строится по той же схеме: группировка по периоду и всем измерениям, условие ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1. Такие дубли часто появляются после нештатных загрузок или обменов.

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

Проверка результата и производительность

Перед тем как доверять запросу, выполните его в консоли запросов и сверьте несколько групп вручную: откройте найденные элементы и убедитесь, что они действительно дубли по вашему критерию. Полезный контроль — суммарное количество записей в выборке должно быть не меньше удвоенного количества групп дублей.

На больших таблицах (миллионы записей) группировка по неиндексированному реквизиту может выполняться долго. Ускорить помогает предварительное сужение выборки в секции ГДЕ: например, искать дубли только среди элементов, созданных за период загрузки, или только внутри одной папки справочника.

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

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

Состав групп дублей
Норма

В каждой группе значения ключевых полей действительно совпадают

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

В одну группу попали записи с пустым ключом — забыт фильтр в ГДЕ

Количество строк в итоговой выборке
Норма

Равно сумме записей по всем группам дублей

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

Строк больше ожидаемого — вероятно, лишнее соединение размножило записи

Повтор одной и той же ссылки
Норма

Каждая ссылка встречается один раз

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

Ссылки задвоены — забыто ключевое слово РАЗЛИЧНЫЕ при самосоединении

Типичные ошибки при поиске дублей

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

Вторая группа ошибок связана с данными: не исключены пустые значения ключа, из-за чего тысячи элементов без ИНН собираются в одну «группу дублей»; не учтён регистр букв и пробелы; в группировку включено поле, которое у разных дублей различается (например, дата создания), и реальные дубли разваливаются на отдельные группы.

Типичные ошибки
01
Условие КОЛИЧЕСТВО(*) > 1 записано в ГДЕ вместо ИМЕЮЩИЕ — запрос падает или фильтрует не то
02
Не исключены пустые значения ключа — все элементы без ИНН сливаются в одну ложную группу
03
Группировка по ссылке вместо смысловых реквизитов — дублей не находится никогда
04
Забыто РАЗЛИЧНЫЕ при самосоединении — каждая пара дублей выводится многократно
05
Удаление дублей сразу по результату запроса без резервной копии и проверки ссылок

Ответы на частые вопросы

Чем ИМЕЮЩИЕ отличается от ГДЕ в запросе 1С?

ГДЕ фильтрует строки до группировки и не может ссылаться на агрегатные функции. ИМЕЮЩИЕ применяется после группировки и работает с агрегатами — именно там пишется условие КОЛИЧЕСТВО(*) > 1 для поиска дублей.

Как найти дубли по наименованию без учёта регистра?

Сгруппируйте по выражению ВРЕГ(СОКРЛП(Наименование)) и добавьте ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1. Учтите, что СОКРЛП убирает пробелы только по краям строки; двойные пробелы внутри потребуют предварительной обработки данных.

Почему запрос с самосоединением выводит каждую пару дважды?

Потому что соединение находит обе комбинации: запись А с записью Б и запись Б с записью А. Добавьте РАЗЛИЧНЫЕ по ссылке или условие вида Т1.Ссылка < Т2.Ссылка, если нужны именно пары.

Можно ли группировать по полю с неограниченной длиной строки?

Нет, запрос завершится ошибкой. Сначала приведите поле к фиксированной длине: ВЫРАЗИТЬ(Поле КАК СТРОКА(150)) — и группируйте по этому выражению.

Как найти дубли записей в периодическом регистре сведений?

Сгруппируйте по периоду и всем измерениям регистра и отберите группы с ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1. Такие дубли чаще всего появляются после загрузок и обменов — проверьте источник данных.

Что быстрее: группировка или самосоединение?

На больших таблицах группировка с ИМЕЮЩИЕ и последующим соединением с исходной таблицей обычно быстрее, так как не порождает попарных комбинаций. Самосоединение удобнее для наглядного сравнения пар, но хуже масштабируется.

Итог

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

Дубли в запросе 1С выбирают группировкой по ключевым полям с условием ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1; сами записи получают соединением с результатом группировки. Обязательно исключайте пустые ключи, помните про регистр и длину строк, а любые действия по удалению выполняйте только после резервной копии и ручной проверки выборки.