Разработка и Конфигурация · 11 мин
Как удалить дубли из таблицы значений в 1С
Как удалить дубли строк из таблицы значений в 1С: свёртка, запрос, поиск дублей по ключевым колонкам, проверка результата, типичные ошибки и FAQ.
Таблица значений в 1С — универсальная структура для промежуточной обработки данных, но у неё нет встроенного механизма уникальности строк. Дубли появляются при объединении нескольких источников, при выгрузке из запросов с соединениями, при загрузке из файлов и при ручном заполнении. Если такую таблицу передать дальше — в документ, отчёт или обмен — дубли превратятся в задвоенные суммы, повторные строки табличных частей и ошибки проведения.
Удалить дубли можно несколькими способами: методом Свернуть(), через запрос с группировкой, через индексированную таблицу и ручной перебор с поиском. Выбор зависит от того, что считать дублем: полное совпадение всех колонок или совпадение только по ключевым полям, а также от того, нужно ли сохранить сопутствующие данные из «лишних» строк.
Ниже разобраны рабочие варианты с примерами кода, условиями применения и ограничениями каждого подхода.
Что считать дублем: определяем критерий перед удалением
Прежде чем писать код, нужно ответить на вопрос: какие строки считаются дублями. Вариантов два. Первый — полное совпадение значений во всех колонках: такие строки возникают, например, при повторной загрузке одного и того же файла. Второй — совпадение только по ключевым колонкам (номенклатура, контрагент, номер документа), когда остальные поля могут отличаться: количество, цена, комментарий.
От этого зависит и судьба «лишних» строк. Если строки полностью идентичны, достаточно оставить одну из них. Если совпадают только ключи, нужно решить, что делать с различающимися данными: просуммировать количество, взять максимальную цену, оставить первую или последнюю строку. Без этого решения любой автоматический метод даст непредсказуемый результат.
Способ 1. Метод Свернуть() — самый быстрый вариант
Метод Свернуть() — штатный инструмент платформы именно для этой задачи. В простейшем виде он группирует строки по перечисленным колонкам и удаляет повторы. Если суммируемые колонки не указаны, метод просто оставляет по одной строке на уникальную комбинацию значений.
// Удаление полных дублей по всем ключевым колонкам
ТЗ.Свернуть("Номенклатура,Склад,Характеристика");
// Свёртка с суммированием числовых колонок
ТЗ.Свернуть("Номенклатура,Склад", "Количество,Сумма");
Важное ограничение: все колонки, которые не входят ни в группировочные, ни в суммируемые, будут удалены из таблицы. Если в таблице есть колонка «Комментарий» или «Ответственный», и она не указана в параметрах, после свёртки её не станет. Поэтому перед вызовом проверьте состав колонок и при необходимости сделайте копию таблицы.
Ещё один нюанс — типы данных. Суммироваться могут только числовые колонки. Если колонка «Количество» имеет составной тип или содержит строки, результат будет некорректным. Метод работает быстро даже на больших таблицах, поэтому это первый кандидат при полных дублях.
Способ 2. Удаление дублей через запрос
Если таблица большая или данные проще обработать средствами СУБД, таблицу значений можно передать в запрос как временную таблицу и сгруппировать. Это удобно, когда нужна сложная агрегация: максимум, минимум, количество дублей, соединение со справочниками для проверки актуальности.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Склад КАК Склад,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ &ТЗ КАК ТЗ
|;
|ВЫБРАТЬ
| Данные.Номенклатура,
| Данные.Склад,
| СУММА(Данные.Количество) КАК Количество
|ИЗ ВТ_Данные КАК Данные
|СГРУППИРОВАТЬ ПО Данные.Номенклатура, Данные.Склад";
Запрос.УстановитьПараметр("ТЗ", ТЗ);
ТЗБезДублей = Запрос.Выполнить().Выгрузить();
Плюс подхода — гибкость: можно посчитать КОЛИЧЕСТВО(*) и сразу увидеть, какие ключи дублировались и сколько раз. Минус — накладные расходы на передачу таблицы в запрос и обратно, а также требование, чтобы состав и типы колонок таблицы были однозначно определены (пустая таблица без типизированных колонок вызовет ошибку).
Способ 3. Ручной перебор с поиском по ключу
Когда критерий дубля нестандартный — например, нужно оставить строку с максимальной датой или первую по порядку, — удобнее перебрать строки вручную. Классическая схема: новая таблица-результат и поиск уже добавленных строк через НайтиСтроки() со структурой отбора.
Результат = ТЗ.СкопироватьКолонки();
Для Каждого Строка ИЗ ТЗ Цикл
Отбор = Новый Структура("Номенклатура,Склад",
Строка.Номенклатура, Строка.Склад);
Найденные = Результат.НайтиСтроки(Отбор);
Если Найденные.Количество() = 0 Тогда
НоваяСтрока = Результат.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
Иначе
// Например, оставляем максимальное количество
Если Строка.Количество > Найденные[0].Количество Тогда
Найденные[0].Количество = Строка.Количество;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Для ускорения поиска на больших таблицах добавьте индекс по ключевым колонкам: Результат.Индексы.Добавить("Номенклатура,Склад"). Без индекса каждый вызов НайтиСтроки() перебирает таблицу целиком, и на десятках тысяч строк алгоритм станет заметно медленным.
Альтернатива — использовать соответствие как словарь ключей: ключом служит строковое представление комбинации значений, значением — ссылка на строку результата. Это быстрее НайтиСтроки() на очень больших таблицах, но требует аккуратно формировать ключ, чтобы значения разных типов не «склеивались» в одинаковые строки.
Сравнение способов
Полные дубли или суммирование по ключу. Самый быстрый и короткий код, но удаляет неиспользуемые колонки.
Большие таблицы, сложная агрегация, подсчёт количества дублей. Требует типизированных колонок и менеджера временных таблиц.
Нестандартный критерий выбора строки: максимум, первая/последняя, объединение текстовых полей. Медленнее, нужен индекс.
Как проверить результат и найти дубли до удаления
Перед удалением полезно оценить масштаб проблемы: сколько строк дублируется и по каким ключам. Простой способ — тот же запрос с группировкой и условием ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1. Он покажет только проблемные комбинации и их кратность, не трогая исходные данные.
После удаления дублей проверьте три контрольные точки: итоговое количество строк, контрольные суммы по числовым колонкам и отсутствие повторов по ключу. Контрольная сумма особенно важна при свёртке с суммированием: сумма по колонке «Количество» до и после должна совпадать, если вы суммировали дубли, и уменьшиться, если лишние строки отбрасывались.
Как проверить результат
Строк стало меньше или столько же, сколько уникальных ключей
Таблица пустая или количество строк не изменилось при заведомых дублях
Итог совпадает с ожидаемой логикой (сумма сохранена или осознанно уменьшена)
Суммы обнулились или неожиданно изменились
Все нужные колонки на месте
После Свернуть() пропали колонки, не указанные в параметрах
Запрос с ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1 возвращает пустой результат
Дубли по ключу остались
Типичные ошибки и ограничения
Самая частая ошибка — свёртка «вживую» над таблицей, которая используется дальше. Метод Свернуть() изменяет исходную таблицу значений, а не возвращает новую. Если та же таблица передаётся в другую процедуру или отображается на форме, последствия будут неожиданными. Работайте с копией через Скопировать().
Вторая группа ошибок связана со сравнением значений. Строки с различающимися пробелами или регистром символов — это разные значения, и свёртка их не объединит. Ссылочные значения сравниваются корректно, а вот значения типа NULL или неопределённого типа в колонках могут привести к тому, что визуально одинаковые строки останутся разными. При загрузке из внешних источников заранее нормализуйте данные: СокрЛП() для строк, приведение типов для чисел.
Третья ошибка — попытка суммировать колонки составного типа. Если колонка объявлена как «Число или Строка», суммирование даст непредсказуемый результат или ошибку. Перед свёрткой убедитесь, что суммируемые колонки строго числовые.
Когда дубли — симптом, а не проблема
Если дубли появляются регулярно, стоит найти их источник, а не только чистить таблицу постфактум. Частые причины: соединение в запросе по неуникальному ключу (например, LEFT JOIN к таблице, где на одну запись приходится несколько связанных), повторное выполнение загрузки без очистки, объединение таблиц через ЗаполнитьЗначенияСвойств в цикле без проверки существования строки.
Исправление источника обычно надёжнее: правильное условие соединения, флаг «загружено», проверка перед добавлением строки. Удаление дублей остаётся валидным инструментом для разовых обработок и интеграций, но в штатных механизмах лучше не допускать их появления.
- 1Определите критерий дубля: полное совпадение строк или совпадение по ключевым колонкам
- 2Решите, что делать с различающимися данными: суммировать, брать максимум, оставлять первую строку
- 3Сделайте копию таблицы через Скопировать()
- 4Примените подходящий способ: Свернуть(), запрос с группировкой или перебор с поиском
- 5Проверьте результат: количество строк, контрольные суммы, отсутствие повторов по ключу
Частые вопросы
Удаляет ли Свернуть() исходную таблицу или возвращает новую?
Метод изменяет ту таблицу, у которой вызван, и ничего не возвращает. Если исходные данные нужны дальше, предварительно создайте копию через Скопировать() и сворачивайте её.
Как удалить дубли, оставив строку с максимальной датой?
Отсортируйте таблицу по дате по убыванию (ТЗ.Сортировать("Дата Убыв")), затем переносите строки в новую таблицу, пропуская те, чей ключ уже встречался. Первая встреченная строка по каждому ключу будет иметь максимальную дату.
Почему Свернуть() не объединил визуально одинаковые строки?
Чаще всего значения отличаются незаметно: лишние пробелы, разный регистр, разные типы данных в колонке (число против строки). Нормализуйте значения перед свёрткой — СокрЛП() для строк и явное приведение типов.
Можно ли удалить дубли в табличной части документа так же, как в таблице значений?
Напрямую метод Свернуть() у табличной части недоступен. Выгрузите табличную часть в таблицу значений методом Выгрузить(), обработайте её, затем очистите табличную часть и загрузите результат обратно методом Загрузить().
Что быстрее на больших таблицах: Свернуть() или запрос?
Для простой свёртки по ключу с суммированием метод Свернуть() обычно быстрее, так как не тратит время на передачу данных в запрос и обратно. Запрос оправдан, когда нужна сложная агрегация или соединение с данными информационной базы.
Как посчитать количество дублей, не удаляя их?
Передайте таблицу в запрос, сгруппируйте по ключевым колонкам с КОЛИЧЕСТВО() и отберите группы условием ИМЕЮЩИЕ КОЛИЧЕСТВО() > 1. Результат покажет проблемные ключи и кратность повторов, исходная таблица не изменится.
Что важно запомнить
Для полных дублей и суммирования по ключу используйте Свернуть() — предварительно сделав копию таблицы. Для сложной агрегации подойдёт запрос с группировкой, для нестандартного выбора строки — перебор с НайтиСтроки() и индексом. Всегда проверяйте результат: количество строк, контрольные суммы и отсутствие повторов по ключу.