К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как убрать дубли из запроса 1С

Способы убрать дубли из запроса 1С: РАЗЛИЧНЫЕ, СГРУППИРОВАТЬ ПО, итоги и обработка таблицы значений. Разбор типичных причин задвоения строк и ошибок.

Дубли строк в результате запроса 1С — одна из самых частых проблем при разработке отчётов и обработок. Они появляются, когда запрос соединяет таблицы, у которых на одну строку «левой» стороны приходится несколько строк «правой», или когда в выборку попадают поля, делающие строки формально разными. Понимание причины задвоения важнее самого приёма устранения: если просто добавить РАЗЛИЧНЫЕ, можно скрыть ошибку в логике и получить неверные суммы.

В языке запросов 1С есть несколько рабочих инструментов: конструкция РАЗЛИЧНЫЕ, группировка с агрегатными функциями, итоги по группировкам, а также постобработка результата средствами встроенного языка (Свернуть у таблицы значений). Каждый способ решает свою задачу и имеет ограничения по производительности и корректности данных.

Ниже разобраны все основные подходы с примерами кода, критериями выбора и типичными ошибками, из-за которых дубли возвращаются снова.

Почему в запросе появляются дубли

Прежде чем устранять повторы, полезно понять их источник. Самая распространённая причина — соединение таблиц по условию «один ко многим». Например, вы выбираете заказы и присоединяете табличную часть товаров: каждый заказ с тремя строками товаров даст три строки в результате. Формально это не дубли, но если вам нужен был список заказов, выглядит именно как задвоение.

Вторая причина — лишнее поле в списке выборки. Если выбрать контрагента и добавить поле «Договор», то один контрагент с пятью договорами появится пять раз. Строки технически разные, но по смыслу задачи — дубли.

Третья причина — виртуальные таблицы регистров без нужных отборов. Например, таблица остатков регистра накопления, развёрнутая по всем измерениям, даст несколько строк на один товар, если товар хранится на разных складах. Наконец, дубли возникают при объединении через ОБЪЕДИНИТЬ (без ВСЕ) там, где подзапросы пересекаются, и при соединении с таблицей, содержащей физически одинаковые записи.

Дубли с разными значениями одного поляЛишнее поле в выборке

Уберите поле из списка выборки или вынесите его в агрегат

Одна строка умножается на N строкСоединение один-ко-многим

Проверьте, не присоединяется ли табличная часть или детальная таблица

Полностью идентичные строкиДубли в источнике или пересечение подзапросов

Используйте РАЗЛИЧНЫЕ и проверьте ОБЪЕДИНИТЬ

Дубли только в отчёте СКДНастройки группировок и ресурсов

Проверьте роли полей и выбранные ресурсы в схеме компоновки

Способ 1. Ключевое слово РАЗЛИЧНЫЕ

Конструкция РАЗЛИЧНЫЕ убирает полностью совпадающие строки из результата. Она ставится сразу после слова ВЫБРАТЬ и применяется ко всей комбинации выбираемых полей:

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

ЗаказыТовары.Ссылка.Контрагент КАК Контрагент

ИЗ

Документ.ЗаказКлиента.Товары КАК ЗаказыТовары

ГДЕ

ЗаказыТовары.Ссылка.Проведен

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

Важное ограничение: РАЗЛИЧНЫЕ сравнивает всю строку целиком. Если в выборке есть поле, которое отличается между строками (например, номенклатура или сумма), строки не схлопнутся. Поэтому типичная ошибка — добавить РАЗЛИЧНЫЕ и не получить эффекта, потому что в списке полей остался «разделяющий» реквизит. Решение — убрать это поле из выборки или перейти к группировке.

Способ 2. Группировка с агрегатными функциями

Когда дубли нужно не просто убрать, а свернуть с расчётом итогов — сумм, количества, максимальных дат — используется СГРУППИРОВАТЬ ПО. Все неагрегатные поля перечисляются в группировке, остальные оборачиваются в функции СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ:

ВЫБРАТЬ

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

СУММА(Продажи.Количество) КАК Количество,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(, , , ) КАК Продажи

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

Продажи.Номенклатура

Группировка — правильный ответ на дубли, возникшие из-за детализации. Если один товар встречается в десяти документах, СУММА соберёт его в одну строку, тогда как РАЗЛИЧНЫЕ оставил бы все десять (строки разные). Для подсчёта уникальных значений внутри группы есть приём КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) — например, число уникальных контрагентов по менеджеру.

Частая ошибка — забыть включить поле в СГРУППИРОВАТЬ ПО или, наоборот, сгруппировать по слишком детальному полю. Если сгруппировать продажи по номенклатуре и документу, дубли по номенклатуре останутся — по одной строке на каждый документ. Правило простое: в группировку попадает ровно тот уровень детализации, который нужен в результате, не глубже.

bsl
ВЫБРАТЬ Менеджер, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Контрагент) КАК ЧислоКлиентов ИЗ РегистрНакопления.Продажи.Обороты СГРУППИРОВАТЬ ПО Менеджер

Способ 3. Свертка таблицы значений после запроса

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

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

ТаблицаРезультата.Свернуть("Контрагент, Договор", "Сумма, Количество");

После вызова останутся уникальные комбинации Контрагент + Договор, а суммы и количества сложатся. Если суммировать нечего, второй параметр можно опустить — получится аналог РАЗЛИЧНЫЕ по выбранным колонкам, причём остальные колонки будут удалены из таблицы.

Этот способ оправдан, когда логика свёртки сложнее, чем позволяет запрос: например, сначала нужно дорассчитать колонки кодом, а потом схлопнуть строки. Минус — весь детальный результат сначала загружается в память, что на больших выборках расточительно. По возможности сворачивайте данные ещё в запросе, а Свернуть используйте как финальный штрих.

Сравнение вариантов

РАЗЛИЧНЫЕ

Нужны уникальные строки без расчётов; не работает, если строки различаются хотя бы одним полем

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

Нужна свёртка с суммами и другими агрегатами; требует аккуратного выбора уровня группировки

Свернуть() у таблицы значений

Данные уже обрабатываются кодом или свёртка зависит от дорассчитанных колонок; расходует память на полную выборку

Исправление соединений

Дубли вызваны лишним соединением; единственный способ, который устраняет причину, а не симптом

Дубли при соединении таблиц: устраняем причину

Если дубли порождает соединение, косметические средства вроде РАЗЛИЧНЫЕ маскируют проблему и могут исказить суммы. Правильный подход — изменить структуру запроса. Типовые приёмы:

  • Заменить соединение с детальной таблицей на соединение со сгруппированным вложенным запросом: сначала СГРУППИРОВАТЬ ПО ключу связи, потом соединять один-к-одному.
  • Вынести «размножающие» данные в отдельный запрос пакета и объединять результаты уже в коде или в СКД через связь наборов данных.
  • Использовать условие соединения с отбором одной строки — например, через вложенный запрос с МАКСИМУМ по дате для получения последнего значения (срез последних на каждую дату вместо таблицы с историей).
ВЫБРАТЬ

Заказы.Ссылка КАК Заказ,

ЕСТЬNULL(Товары.СуммаДокумента, 0) КАК Сумма

ИЗ

Документ.ЗаказКлиента КАК Заказы

ЛЕВОЕ СОЕДИНЕНИЕ (

ВЫБРАТЬ Товары.Ссылка КАК Ссылка, СУММА(Товары.Сумма) КАК СуммаДокумента

ИЗ Документ.ЗаказКлиента.Товары КАК Товары

СГРУППИРОВАТЬ ПО Товары.Ссылка

) КАК Товары

ПО Заказы.Ссылка = Товары.Ссылка

Здесь табличная часть предварительно свёрнута до одной строки на заказ, поэтому соединение не размножает строки. Такой приём — стандартный способ безопасно присоединять агрегаты к шапкам документов.

Дубли в СКД и динамических списках

В отчётах на СКД задвоение часто происходит не в самом запросе, а на уровне схемы: поле добавлено в ресурсы без агрегата, включена лишняя группировка или у связи наборов данных неверно указаны параметры. Проверяйте в первую очередь закладку «Ресурсы» — каждое числовое поле должно иметь агрегатное выражение (Сумма, Максимум и т.п.), иначе платформа может вывести строки детальнее, чем ожидалось.

В динамических списках дубли критичнее: платформа требует уникальности ключевого поля. Если основная таблица списка соединяется с чем-то «один-ко-многим», список может показывать повторы ссылок и некорректно работать при позиционировании. Лечение то же — свёртка присоединяемых данных до одной строки на ключ либо отказ от соединения в пользу вычисляемых полей.

Типичные ошибки
01
Добавить РАЗЛИЧНЫЕ, но оставить в выборке поле, которое различает строки, — дубли остаются
02
Группировать по более детальному полю, чем нужно, — одна сущность всё равно выводится несколькими строками
03
Применять ОБЪЕДИНИТЬ вместо ОБЪЕДИНИТЬ ВСЕ (или наоборот) без понимания разницы: первое убирает дубли между подзапросами, второе сохраняет
04
Соединять шапку документа напрямую с табличной частью и удивляться размножению строк
05
Убирать дубли методом Свернуть, забыв перечислить суммируемые колонки, — числовые данные теряются

Как проверить, что дубли убраны корректно

После правки запроса проверьте результат по трём направлениям. Первое — количество строк: выведите КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КлючевоеПоле) и сравните с общим числом строк результата; они должны совпадать, если ключ должен быть уникален. Второе — контрольные суммы: итог по суммовым полям до и после свёртки не должен меняться, если вы не отбрасывали данные намеренно.

Третье — сверка с эталоном. Для отчётов по регистрам удобно сверить итоги с типовым отчётом (например, оборотно-сальдовой ведомостью или отчётом по продажам) на том же периоде и отборе. Расхождение означает, что свёртка либо соединение исказили данные.

Контрольные точки

Как проверить результат

Число строк результата
Норма

Равно числу уникальных значений ключевого поля

Тревожный признак

Строк больше — дубли остались

Итоговые суммы
Норма

Совпадают с суммами до свёртки и с типовым отчётом

Тревожный признак

Суммы изменились — данные потеряны или задвоены

Динамический список
Норма

Каждая ссылка отображается один раз, позиционирование работает

Тревожный признак

Повторы ссылок, скачки курсора — неуникальный ключ

FAQ

Чем РАЗЛИЧНЫЕ отличается от СГРУППИРОВАТЬ ПО?

РАЗЛИЧНЫЕ убирает полностью идентичные строки и не выполняет никаких расчётов. СГРУППИРОВАТЬ ПО объединяет строки по указанным полям и позволяет вычислять агрегаты — суммы, количества, максимумы. Если нужны только уникальные значения без расчётов, оба способа дадут одинаковый результат, но РАЗЛИЧНЫЕ записывается короче.

Почему РАЗЛИЧНЫЕ не убирает дубли в моём запросе?

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

Как посчитать количество уникальных значений в запросе?

Используйте конструкцию КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) внутри запроса с группировкой. Например, число уникальных покупателей по каждому менеджеру: сгруппируйте по менеджеру и выведите КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Контрагент).

Что выбрать: ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ?

ОБЪЕДИНИТЬ автоматически убирает дубли между подзапросами, но требует дополнительной обработки на сервере СУБД. ОБЪЕДИНИТЬ ВСЕ быстрее и сохраняет все строки. Если подзапросы заведомо не пересекаются (например, разные регистры), используйте ОБЪЕДИНИТЬ ВСЕ — это стандартная практика оптимизации.

Можно ли убрать дубли из результата запроса без изменения самого запроса?

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

Влияет ли РАЗЛИЧНЫЕ на производительность запроса?

Да, устранение дублей требует сортировки или хеширования результата на стороне СУБД. На небольших выборках это незаметно, на миллионах строк с десятками полей — ощутимо. Сокращайте список полей до минимума и, где возможно, заменяйте РАЗЛИЧНЫЕ группировкой по индексированным полям.

Итог

Что важно запомнить

Сначала найдите причину задвоения — лишнее поле, соединение один-ко-многим или детализация регистра. Для уникальных строк используйте РАЗЛИЧНЫЕ, для свёртки с расчётами — СГРУППИРОВАТЬ ПО, для постобработки в коде — Свернуть(). После исправления сверьте количество строк и итоговые суммы с эталоном.