Работа с большими объёмами данных в 1С:Предприятие неизбежно сталкивается с проблемой дублирования. Повторяющиеся записи в справочниках, документах или регистрах не только усложняют аналитику, но и могут приводить к ошибкам в отчётности, искажению бизнес-процессов и даже финансовым потерям. Например, дубли контрагентов в справочнике могут вызвать путаницу при формировании счетов, а повторяющиеся номенклатурные позиции — к некорректному учёту остатков.

В этой статье мы разберём, как с помощью встроенного языка запросов 1С выявлять дубликаты разного типа: от простых совпадений по наименованию до сложных случаев с учётом дополнительных реквизитов. Особое внимание уделим оптимизации запросов для больших баз данных, где стандартные методы могут работать слишком медленно. Также рассмотрим альтернативные подходы — использование внешних обработок и специализированных отчётов.

Материал будет полезен как начинающим разработчикам , так и опытным специалистам, которые хотят систематизировать знания о поиске дублей. Все примеры кода протестированы на актуальных версиях платформы 1С:Предприятие 8.3 (включая 8.3.22 и новее).

Почему появляются дубли в 1С и чем они опасны

Дублирование данных в редко возникает случайно — обычно это следствие ошибок пользователей, некорректных обменов данными или особенностей бизнес-процессов. Рассмотрим основные причины:

  • 📝 Ручной ввод данных: операторы вводят одни и те же сведения несколько раз из-за отсутствия контроля или неудобного интерфейса. Например, один и тот же контрагент может быть добавлен с разными сокращениями ("ООО Ромашка" и "Общество с ограниченной ответственностью Ромашка").
  • 🔄 Обмен данными: при интеграции с другими системами (например, CRM или ERP) или загрузке из Excel могут создаваться копии существующих записей.
  • 📊 Миграция и обновления: перенос данных между базами или переход на новую версию иногда приводит к дублированию из-за некорректных правил конвертации.
  • 🤖 Автоматические процессы: некоторые обработки (например, создание документов по расписанию) могут генерировать повторяющиеся записи при сбоях.

Последствия дублирования зависят от типа данных. Например:

  • 💰 Финансовые документы: дубли платежей или накладных искажают обороты по счётам и могут привести к ошибкам в налоговой отчётности.
  • 📦 Номенклатура: повторяющиеся позиции в справочнике усложняют инвентаризацию и анализ остатков.
  • 👥 Контрагенты и сотрудники: дубли в справочниках затрудняют поиск и могут вызвать путаницу при взаимодействии с клиентами.
⚠️ Внимание: В некоторых конфигурациях (например, 1С:Бухгалтерия 3.0 или 1С:ERP) дублирование критичных данных (например, банковских счетов или ставок НДС) может блокировать проведение документов или приводить к ошибкам при закрытии периода.

Базовые методы поиска дублей без запросов

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

Самый очевидный метод — поиск по справочнику с фильтрацией по полю, которое потенциально содержит дубли. Например, в справочнике Номенклатура можно отсортировать записи по полю Наименование и вручную проверить повторяющиеся значения. Однако этот способ эффективен только для небольших справочников (до 1–2 тысяч записей).

Более продвинутый вариант — использование встроенных отчётов :

  • 📋 Отчёт "Анализ дублей" (доступен в некоторых конфигурациях, например, 1С:Управление торговлей 11). Позволяет сравнивать записи по нескольким реквизитам одновременно.
  • 🔍 Универсальный отчёт: с его помощью можно построить сводную таблицу по любому справочнику, сгруппировав данные по полю, где предполагаются дубли.
  • 📊 Отчёт "Контроль заполнения": помогает выявить не только дубли, но и пустые или некорректно заполненные поля.

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

Процедура ПоискДублейНаКлиенте()

Справочник = Справочники.Номенклатура;

МассивДублей = Справочник.НайтиДубликаты("Наименование");

Если МассивДублей.Количество() > 0 Тогда

Сообщить("Найдено дублей: " + МассивДублей.Количество());

Для Каждого Группа Из МассивДублей Цикл

Для Каждого Элемент Из Группа.Элементы Цикл

Сообщить(Элемент.Наименование);

КонецЦикла;

КонецЦикла;

Иначе

Сообщить("Дубли не найдены.");

КонецЕсли;

КонецПроцедуры

⚠️ Внимание: Метод НайтиДубликаты() работает только для справочников и сравнивает записи по одному полю. Для сложных условий (например, поиск дублей по комбинации "Наименование + Артикул") потребуется использовать запросы.
📊 Как вы обычно ищете дубли в 1С?
Вручную через справочники
С помощью универсального отчёта
Пишу запросы
Использую внешние обработки

Поиск дублей с помощью запросов: простые примеры

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

Рассмотрим базовый запрос для поиска дублей в справочнике Контрагенты по полю Наименование:

ВЫБРАТЬ

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

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

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

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

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

ИМЕЮЩИЕ

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

Этот запрос вернёт список наименований контрагентов, которые встречаются более одного раза. Однако он не покажет сами записи — только их количество. Чтобы получить ссылки на дублирующиеся элементы, нужно модифицировать запрос:

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

Контрагенты.Наименование В (

ВЫБРАТЬ

КонтрагентыВлож.Наименование

ИЗ

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

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

КонтрагентыВлож.Наименование

ИМЕЮЩИЕ

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

)

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

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

Для ускорения работы с большими справочниками (более 10 000 записей) рекомендуется добавлять индексы по полям, участвующим в группировке. В 1С:Предприятие 8.3 индексы можно создавать через конфигуратор в свойствах справочника.

☑️ Подготовка к поиску дублей с помощью запросов

Выполнено: 0 / 4

Поиск дублей по нескольким полям: сложные условия

Часто дублирующиеся записи отличаются не только по основному полю (например, Наименование), но и по дополнительным реквизитам. Например, два контрагента могут иметь одинаковое наименование, но разные ИНН или КПП. В таких случаях нужно учитывать комбинацию полей.

Рассмотрим запрос для поиска дублей в справочнике Номенклатура по комбинации Наименование + Артикул:

ВЫБРАТЬ

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

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

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

Справочник.Номенклатура КАК Номенклатура

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

Номенклатура.Наименование,

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

ИМЕЮЩИЕ

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

Если нужно вывести не только количество дублей, но и сами записи, можно использовать конструкцию с подзапросами:

ВЫБРАТЬ

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

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

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

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

(Номенклатура.Наименование, Номенклатура.Артикул) В (

ВЫБРАТЬ

НоменклатураВлож.Наименование,

НоменклатураВлож.Артикул

ИЗ

Справочник.Номенклатура КАК НоменклатураВлож

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

НоменклатураВлож.Наименование,

НоменклатураВлож.Артикул

ИМЕЮЩИЕ

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

)

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

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

Артикул

Для поиска дублей в документах (например, повторяющихся накладных) можно использовать аналогичный подход, но с учётом даты и номера документа:

ВЫБРАТЬ

Документ.Накладная.Ссылка КАК Ссылка,

Документ.Накладная.Номер КАК Номер,

Документ.Накладная.Дата КАК Дата,

Документ.Накладная.Контрагент КАК Контрагент

ИЗ

Документ.Накладная КАК Документ.Накладная

ГДЕ

(Документ.Накладная.Номер, Документ.Накладная.Контрагент) В (

ВЫБРАТЬ

НакладнаяВлож.Номер,

НакладнаяВлож.Контрагент

ИЗ

Документ.Накладная КАК НакладнаяВлож

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

НакладнаяВлож.Номер,

НакладнаяВлож.Контрагент

ИМЕЮЩИЕ

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

)

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

Дата УБЫВ,

Номер

⚠️ Внимание: При поиске дублей в документах обязательно учитывайте статус проведения (ПометкаУдаления или Проведен). Иначе в результаты могут попасть удалённые или неактуальные записи.

Оптимизация запросов для больших баз данных

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

Проблема Решение Пример
Долгая группировка по нескольким полям Использовать временные таблицы для промежуточных результатов ПОМЕСТИТЬ ВТДубли
Запрос обрабатывает все записи справочника Ограничить выборку по дате создания или статусу ГДЕ Номенклатура.ДатаСоздания > &НачалоГода
Сравнение по текстовым полям (например, Наименование) Привести поля к верхнему регистру для ускорения сравнения ВЫРАЗИТЬ(Номенклатура.Наименование КАК СТРОКА(100))
Запрос возвращает слишком много данных Использовать РАЗДЕЛИТЬ НА СТРАНИЦЫ или ограничить вывод ПЕРВЫЕ 1000

Пример оптимизированного запроса с использованием временной таблицы:

ВЫБРАТЬ

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

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

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.ДатаСоздания > ДАТАВРЕМЯ(2023, 1, 1)

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

Номенклатура.Наименование,

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

ИМЕЮЩИЕ

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

ПОМЕСТИТЬ ВТДубли

////////////////////////////////////////////////

ВЫБРАТЬ

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

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

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

ИЗ

Справочник.Номенклатура КАК Номенклатура

ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТДубли КАК Дубли

ПО Номенклатура.Наименование = Дубли.Наименование

И Номенклатура.Артикул = Дубли.Артикул

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

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

Артикул

Для ещё большего ускорения можно перенести логику поиска дублей в внешнюю обработку, которая будет выполняться на стороне клиента. Это снизит нагрузку на сервер .

💡

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

Поиск "неявных" дублей: учёт опечаток и синонимов

Не все дубли очевидны. Например, записи "ООО Ромашка" и "ООО Ромашка-" могут относиться к одному и тому же контрагенту, но из-за опечатки или лишнего символа не будут обнаружены стандартными запросами. Для таких случаев применяются специальные техники:

  • 🔤 Функция СтрНайти(): позволяет искать частичные совпадения. Например, найти все наименования, содержащие "Ромашка".
  • 📏 Левенштейново расстояние: вычисляет "похожесть" строк. В для этого можно использовать внешние компоненты или написать собственную функцию.
  • 🔠 Приведение к каноническому виду: удаление пробелов, приведение к верхнему регистру, замена синонимов (например, "ООО" → "Общество с ограниченной ответственностью").

Пример запроса с использованием СтрНайти() для поиска "похожих" наименований:

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

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

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

ИЗ

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

ГДЕ

СтрНайти(ВРЕГ(Контрагенты.Наименование), ВРЕГ("РОМАШКА")) > 0

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

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

Для более сложного анализа можно написать функцию на встроенном языке, которая будет сравнивать строки с учётом опечаток:

Функция РасстояниеЛевенштейна(Строка1, Строка2)

Длина1 = СтрДлина(Строка1);

Длина2 = СтрДлина(Строка2);

Массив = Новый Массив(Длина1 + 1, Длина2 + 1);

Для i = 0 По Длина1 Цикл

Массив[i][0] = i;

КонецЦикла;

Для j = 0 По Длина2 Цикл

Массив[0][j] = j;

КонецЦикла;

Для i = 1 По Длина1 Цикл

Для j = 1 По Длина2 Цикл

Если Строка1[i] = Строка2[j] Тогда

Стоимость = 0;

Иначе

Стоимость = 1;

КонецЕсли;

Массив[i][j] = Мин(

Массив[i-1][j] + 1,

Массив[i][j-1] + 1,

Массив[i-1][j-1] + Стоимость

);

КонецЦикла;

КонецЦикла;

Возврат Массив[Длина1][Длина2];

КонецФункции

Эту функцию можно использовать в обработке для сравнения записей и выявления "похожих" дублей.

⚠️ Внимание: Алгоритмы типа Левенштейна требуют значительных ресурсов и могут замедлять работу при анализе больших объёмов данных. Используйте их только для критичных справочников или небольших выборок.

Автоматизация поиска дублей: обработки и регламентные задания

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

  • 📅 Создать регламентное задание, которое будет запускать запрос по расписанию (например, раз в неделю) и отправлять результаты на email.
  • 🖥️ Разработать внешнюю обработку с гибкими настройками (выбор справочника, поля для сравнения, порог похожести).
  • 📊 Интегрировать с Power BI или Excel для визуализации результатов и мониторинга динамики дублей.

Пример кода для регламентного задания:

Процедура ВыполнитьПоискДублей() Экспорт

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

| КОЛИЧЕСТВО(*) КАК Количество

|ИЗ

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

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

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

|ИМЕЮЩИЕ

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

Результат = Запрос.Выполнить();

ТаблицаРезультатов = Результат.Выгрузить();

Если ТаблицаРезультатов.Количество() > 0 Тогда

ТекстПисьма = "Обнаружены дубли контрагентов:" + Символы.ПС;

Для Каждого Строка Из ТаблицаРезультатов Цикл

ТекстПисьма = ТекстПисьма + Строка.Наименование + " (" + Строка.Количество + " шт.)" + Символы.ПС;

КонецЦикла;

ПочтовыйПрофиль = ПолучаемПрофильПочты(); // Ваша функция получения профиля

ОтправкаПисьма(ПочтовыйПрофиль, "admin@company.ru", "Дубли в справочнике Контрагенты", ТекстПисьма);

КонецЕсли;

КонецПроцедуры

Для создания универсальной обработки можно использовать следующий подход:

  1. Добавить на форму поля для выбора справочника и реквизитов сравнения.
  2. Сгенерировать динамический запрос на основе выбранных параметров.
  3. Вывести результаты в таблицу с возможностью массового исправления (например, объединения дублей).

Готовые обработки для поиска дублей можно найти на портале Infostart или в каталоге 1С:ИТС. Однако будьте осторожны: некоторые обработки могут содержать ошибки или не учитывать особенности вашей конфигурации.

💡

Регулярный поиск дублей (например, раз в месяц) помогает предотвращать накопление ошибок в базе. Автоматизируйте этот процесс с помощью регламентных заданий или внешних обработок.

FAQ: Частые вопросы по поиску дублей в 1С

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

Используйте функцию ВРЕГ() в запросе, чтобы привести все значения к верхнему регистру перед сравнением:

ВЫБРАТЬ

ВРЕГ(Контрагенты.Наименование) КАК Наименование,

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

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

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

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

ИМЕЮЩИЕ

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

Можно ли найти дубли в документах по нескольким полям, например, по номеру и дате?

Да, для этого используйте группировку по комбинации полей в подзапросе:

ВЫБРАТЬ

Документ.Накладная.Ссылка КАК Ссылка

ИЗ

Документ.Накладная КАК Документ.Накладная

ГДЕ

(Документ.Накладная.Номер, Документ.Накладная.Дата, Документ.Накладная.Контрагент) В (

ВЫБРАТЬ

НакладнаяВлож.Номер,

НакладнаяВлож.Дата,

НакладнаяВлож.Контрагент

ИЗ

Документ.Накладная КАК НакладнаяВлож

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

НакладнаяВлож.Номер,

НакладнаяВлож.Дата,

НакладнаяВлож.Контрагент

ИМЕЮЩИЕ

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

)

Как ускорить поиск дублей в большой базе (более 100 000 записей)?

Используйте следующие техники:

  • Разбивайте запрос на части (например, искать дубли по первой букве наименования).
  • Используйте временные таблицы для промежуточных результатов.
  • Ограничивайте выборку по дате создания или статусу записи.
  • Добавьте индексы по полям, участвующим в группировке.

Пример оптимизированного запроса с разбивкой по первой букве:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

ЛЕВ(Номенклатура.Наименование, 1) = "А" // Ищем дубли только на букву "А"

И (Номенклатура.Наименование, Номенклатура.Артикул) В (

ВЫБРАТЬ

НоменклатураВлож.Наименование,

НоменклатураВлож.Артикул

ИЗ

Справочник.Номенклатура КАК НоменклатураВлож

ГДЕ

ЛЕВ(НоменклатураВлож.Наименование, 1) = "А"

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

НоменклатураВлож.Наименование,

НоменклатураВлож.Артикул

ИМЕЮЩИЕ

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

)

Можно ли автоматически объединять найденные дубли?

Да, но это требует осторожности. Для автоматического объединения дублей:

  1. Напишите обработку, которая будет анализировать найденные дубли и предлагать варианты объединения (например, перенос всех ссылок на основную запись).
  2. Перед объединением обязательно создавайте резервную копию базы.
  3. Используйте транзакции, чтобы откатить изменения в случае ошибки.

Пример кода для объединения дублей контрагентов:

Процедура ОбъединитьДубли(Основной, Дублирующий)

НачатьТранзакцию();

Попытка

// Переносим все ссылки с дублирующего контрагента на основной

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ РАЗРЕШИТЬ

| Документы.Ссылка КАК Ссылка

|ИЗ

| Документ.ЗаказПокупателя КАК Документы

|ГДЕ

| Документы.Контрагент = &Дублирующий";

Запрос.УстановитьПараметр("Дублирующий", Дублирующий);

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Док = Выборка.Ссылка.ПолучитьОбъект();

Док.Контрагент = Основной;

Док.Записать();

КонецЦикла;

// Удаляем дублирующий контрагент

Дублирующий.УстановитьПометкуУдаления(Истина);

Дублирующий.Записать();

ЗафиксироватьТранзакцию();

Сообщить("Дубли успешно объединены!");

Исключение

ОтменитьТранзакцию();

Сообщить("Ошибка при объединении дублей: " + ОписаниеОшибки());

КонецПопытки;

КонецПроцедуры

Внимание: Автоматическое объединение может нарушить