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