Как проверить корректность данных справочника и найти повторяющиеся значения

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Метод 1: Использование вложенного запроса с группировкой

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

Основная идея заключается в том, чтобы сначала определить список «проблемных» складов, а затем выбрать все элементы, которые на них ссылаются. Разберем по шагам логику построения условия ГДЕ ... В (ВЫБРАТЬ ...).


ВЫБРАТЬ
    ТО.Ссылка КАК Ссылка,
    ТО.Склад КАК Склад
ИЗ
    Справочник.ТО КАК ТО
ГДЕ
    ТО.Склад В
        (ВЫБРАТЬ
            ТО_Дубли.Склад
        ИЗ
            Справочник.ТО КАК ТО_Дубли
        СГРУППИРОВАТЬ ПО
            ТО_Дубли.Склад
        ИМЕЮЩИЕ
            КОЛИЧЕСТВО(ТО_Дубли.Ссылка) > 1)

В данном примере внутренний запрос выполняет группировку по полю Склад. Оператор ИМЕЮЩИЕ (аналог HAVING в SQL) позволяет нам отфильтровать результаты агрегатной функции КОЛИЧЕСТВО. Если количество ссылок для конкретного склада больше единицы, этот склад попадает в список дублей.

Метод 2: Оптимизация через временные таблицы

Рассмотрим ситуацию, когда база данных содержит сотни тысяч записей. Выполнение вложенного запроса внутри условия ГДЕ может привести к деградации производительности, так как СУБД не всегда эффективно строит план выполнения для таких конструкций. Профессиональные разработчики рекомендуют использовать временные таблицы (МенеджерВременныхТаблиц).

Выясним причину, почему это эффективнее: при использовании временных таблиц 1С сначала вычисляет результат промежуточного запроса, сохраняет его в памяти или в специальной таблице SQL-сервера, а затем выполняет конечное соединение. Это упрощает работу оптимизатора СУБД.


// Шаг 1: Помещаем дубликаты во временную таблицу
ВЫБРАТЬ
    ТО.Склад КАК Склад
ПОМЕСТИТЬ ВТ_ДублиСкладов
ИЗ
    Справочник.ТО КАК ТО
СГРУППИРОВАТЬ ПО
    ТО.Склад
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(ТО.Ссылка) > 1
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Выбираем все данные, сопоставляя с временной таблицей
ВЫБРАТЬ
    ТО.Ссылка КАК Ссылка,
    ТО.Склад КАК Склад
ИЗ
    Справочник.ТО КАК ТО
ГДЕ
    ТО.Склад В (ВЫБРАТЬ ВТ.Склад ИЗ ВТ_ДублиСкладов КАК ВТ)
УПОРЯДОЧИТЬ ПО
    Склад
ИТОГИ ПО
    Склад

Обратите внимание на использование секции ИТОГИ. Это позволяет визуально сгруппировать дубли в отчете или при выводе в дерево значений. Мы сразу видим склад-заголовок и под ним список всех элементов ТО, которые к нему привязаны.

Метод 3: Использование внутреннего соединения

Существует еще один способ решения задачи — через ВНУТРЕННЕЕ СОЕДИНЕНИЕ таблицы самой с собой. Посмотрим на пример реализации:


ВЫБРАТЬ
    ТО1.Ссылка КАК Ссылка,
    ТО1.Склад КАК Склад
ИЗ
    Справочник.ТО КАК ТО1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ 
    Справочник.ТО КАК ТО2 
    ПО (ТО1.Склад = ТО2.Склад) И (ТО1.Ссылка <> ТО2.Ссылка)
СГРУППИРОВАТЬ ПО
    ТО1.Ссылка,
    ТО1.Склад

Здесь мы соединяем таблицу с её копией по совпадению склада, но при условии, что ссылки на элементы разные (ТО1.Ссылка <> ТО2.Ссылка). Если для элемента ТО1 найдется хотя бы один «собрат» с таким же складом, запись попадет в результат. Однако следует помнить, что на очень больших таблицах операция соединения может быть «дорогой» с точки зрения ресурсов сервера.

Важность индексирования реквизитов

Проанализируем техническую сторону вопроса производительности. Любой запрос, который ищет дубли, будет работать быстро только в том случае, если по проверяемому полю построен индекс. Если у реквизита Склад в метаданных не стоит свойство Индексировать, системе придется выполнять полное сканирование всей таблицы (Table Scan). Для справочников с объемом записей более 10 000 это критично. Всегда проверяйте наличие индекса у полей, по которым планируете часто искать совпадения.

Использование типовых инструментов (БСП)

Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), нет необходимости писать код для разовой проверки. Рассмотрим встроенную обработку Поиск и удаление дублей. Разберем её преимущества:

  1. Гибкие правила: Можно искать не только по полному совпадению, но и по «похожим словам» (фонетический поиск).
  2. Безопасность: Программа автоматически проверяет использование ссылок во всех документах системы.
  3. Автоматизация: После объединения дублей система сама «перецепит» все проведенные документы на один выбранный эталонный элемент.

Предотвращение появления дублей

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


Процедура ПередЗаписью(Отказ)
    
    // Проверка на дубли склада при записи
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	ТО.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.ТО КАК ТО
        |ГДЕ
        |	ТО.Склад = &Склад
        |	И ТО.Ссылка <> &Ссылка";
    
    Запрос.УстановитьПараметр("Склад", Склад);
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Внимание! Элемент с таким складом уже существует.";
        Сообщение.Сообщить();
        // Отказ = Истина; // Разкомментируйте, если хотите запретить запись
    КонецЕсли;

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

Таким образом, мы обеспечиваем чистоту данных в режиме реального времени. Если ваша задача — строгий контроль, используйте флаг Отказ = Истина, чтобы заблокировать запись некорректных данных.

Заключение

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

← На главную