Как наиболее эффективно проверить наличие дублей строк в табличной части документа 1С?

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

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

Метод 1: Использование таблицы значений и метода Свернуть()

Этот способ считается классическим и наиболее простым в реализации, если нам достаточно лишь установить сам факт наличия дублей, не указывая пользователю на конкретные строки, следуя шаблонам для применения стандартов и методик разработки. Рассмотрим этот алгоритм подробнее.

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


// Выгружаем только те колонки, по которым ищем дубли
ТаблицаДублей = Товары.Выгрузить( , "Номенклатура, Характеристика, Серия");
// Добавляем колонку для агрегации
ТаблицаДублей.Колонки.Добавить("КоличествоДублей");
ТаблицаДублей.ЗаполнитьЗначения(1, "КоличествоДублей");

// Сворачиваем таблицу по ключевым полям, суммируя единицы
ТаблицаДублей.Свернуть("Номенклатура, Характеристика, Серия", "КоличествоДублей");

// Если количество строк уменьшилось, значит, дубли были
Если ТаблицаДублей.Количество() < Товары.Количество() Тогда
    Сообщить("В табличной части обнаружены дублирующиеся строки!");
    Отказ = Истина;
КонецЕсли;

Преимущества: Простота реализации и высокая скорость работы на небольших и средних объемах данных (до нескольких сотен строк).

Недостатки: Мы теряем информацию о номерах строк, где возникли дубли. Кроме того, для больших таблиц метод может уступать в скорости более оптимизированным алгоритмам.

Метод 2: Проверка с помощью запроса

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

Если документ уже записан в базу данных, запрос к табличной части через обращение к таблице СУБД будет максимально быстрым, особенно если использовать управляемую консоль запросов и отчетов (поможет управляемая консоль запросов и редактор объектов). Выясним, как выглядит такой запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Товары.Номенклатура,
    |	Товары.Характеристика,
    |	Товары.Серия,
    |	КОЛИЧЕСТВО(*) КАК КоличествоСтрок
    |ИЗ
    |	Документ.РеализацияТоваровУслуг.Товары КАК Товары
    |ГДЕ
    |	Товары.Ссылка = &Ссылка
    |ГРУППИРОВАТЬ ПО
    |	Товары.Номенклатура,
    |	Товары.Характеристика,
    |	Товары.Серия
    |ИМЕЮЩИЕ
    |	КОЛИЧЕСТВО(*) > 1";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
    // Обработка найденных дублей
КонецЕсли;

Однако, если мы проводим новый документ, его данных в базе еще нет. В этом случае нам придется передавать ТаблицаЗначений в запрос в качестве параметра. Рассмотрим особенности этого процесса: при передаче внешней таблицы платформа выполняет её сериализацию для передачи на сторону SQL-сервера. На небольших объемах (до 100-200 строк) накладные расходы на эту передачу могут превысить время самой проверки в памяти через Свернуть(). Но если строк тысячи, SQL-сервер справится с группировкой эффективнее встроенного языка.

Метод 3: Использование объекта Соответствие (хеш-таблица)

Проанализируем наиболее технологичный и быстрый способ поиска дублей в оперативной памяти — использование объекта Соответствие. Этот метод позволяет найти дубли за один проход по таблице.

Алгоритм работает по принципу формирования уникального ключа для каждой строки. Ключ может состоять из комбинации значений или быть специальной структурой. Посмотрим на пример реализации:


ПроверяемыеСтроки = Новый Соответствие;
Для Каждого СтрокаТЧ Из Товары Цикл
    // Формируем уникальный ключ (можно через структуру или строку)
    Ключ = Новый Структура("Ном, Хар, Сер", СтрокаТЧ.Номенклатура, СтрокаТЧ.Характеристика, СтрокаТЧ.Серия);
    
    Если ПроверяемыеСтроки.Получить(Ключ) = Неопределено Тогда
        // Таких данных еще не было, запоминаем
        ПроверяемыеСтроки.Вставить(Ключ, Истина);
    Иначе
        // Мы нашли дубль!
        Сообщить("Дубль в строке номер: " + СтрокаТЧ.НомерСтроки);
        Отказ = Истина;
    КонецЕсли;
КонецЦикла;

Почему это быстро? Поиск в объекте Соответствие (хеш-таблица) имеет вычислительную сложность O(1), что значительно быстрее, чем метод НайтиСтроки(), который при каждом вызове выполняет перебор (если не созданы индексы).

Метод 4: Индексация таблицы значений и НайтиСтроки()

Если вам необходимо выполнять проверку "на лету" (например, в событии ПриИзменении колонки), использование НайтиСтроки() оправдано, но при одном условии — наличии индексов. Разберем ситуацию: поиск в ТЧ без индекса при каждой новой строке заставляет систему просматривать все предыдущие строки. На 1000-й строке это будет уже 1000 операций сравнения.

Чтобы ускорить процесс, выполним индексацию:


ТЗ = Товары.Выгрузить();
ТЗ.Индексы.Добавить("Номенклатура, Характеристика, Серия");

ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Номенклатура", ТекущаяНоменклатура);
// ... заполнение остальных полей

НайденныеСтроки = ТЗ.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 1 Тогда
    // Дубли найдены
КонецЕсли;

Метод 5: Сортировка как способ детального анализа

Если бизнес-логика требует не просто отказать в проведении, а вывести пользователю полный список всех задублированных строк с их номерами, эффективно будет использовать сортировку. Проанализируем шаги:

  1. Выгружаем ТЧ в ТаблицаЗначений.
  2. Сортируем её по проверяемым колонкам: ТЗ.Сортировать("Номенклатура, Характеристика, Серия");.
  3. Проходим циклом от второй строки до последней, сравнивая текущую строку с предыдущей.

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

Рекомендации по выбору метода

Подводя итог нашему анализу, выделим лучшие практики:

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

← На главную