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

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

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

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

Дубли строк в результате запроса 1С — одна из самых частых проблем при разработке отчётов и выборок. Причин две: либо в исходных данных действительно повторяются значения и нужно выбрать уникальные, либо дубли появляются из-за соединения таблиц, когда к одной строке левой таблицы подходят несколько строк правой. В обоих случаях проблема решается средствами языка запросов, но инструменты разные.

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

Убираем полностью одинаковые строки через РАЗЛИЧНЫЕ

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

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

Товары.Номенклатура КАК Номенклатура,

Товары.Склад КАК Склад

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

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

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

Убираем дубли по части полей через СГРУППИРОВАТЬ ПО

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

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

СУММА(Товары.Количество) КАК Количество,

СУММА(Товары.Сумма) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

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

Товары.Номенклатура

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

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

Маршрут решения

Как выбрать способ

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

Дубли из-за соединения таблиц: как найти и устранить причину

Самый коварный случай — когда в исходных данных дублей нет, но после ЛЕВОГО СОЕДИНЕНИЯ строки размножились. Причина: к одной строке левой таблицы подошло несколько строк правой, потому что условие связи недостаточно точное. Классический пример — соединение документа с регистром сведений по номенклатуре, когда в регистре несколько записей на одну позицию.

Диагностика простая: добавьте в запрос поле КОЛИЧЕСТВО(*) с группировкой по ключевым полям левой таблицы и найдите строки, где количество больше единицы. Либо просто сравните число строк результата с числом строк левой таблицы — если стало больше, соединение размножает данные.

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

Соединение со сгруппированным вложенным запросом

Универсальный приём против дублей из соединения — заранее свернуть правую таблицу до уровня ключа связи. Вложенный запрос группирует данные, и к каждой строке левой таблицы присоединяется ровно одна строка.

ВЫБРАТЬ

Реализация.Номенклатура КАК Номенклатура,

Цены.Цена КАК Цена

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Реализация

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

ВЫБРАТЬ

ЦеныТаб.Номенклатура КАК Номенклатура,

МАКСИМУМ(ЦеныТаб.Цена) КАК Цена

ИЗ

РегистрСведений.ЦеныНоменклатуры КАК ЦеныТаб

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

ЦеныТаб.Номенклатура) КАК Цены

ПО Реализация.Номенклатура = Цены.Номенклатура

Тот же результат часто дают виртуальные таблицы. Для цен корректнее взять РегистрСведений.ЦеныНоменклатуры.СрезПоследних — он вернёт по одной записи на номенклатуру без ручной группировки и с учётом периодичности регистра.

Если после соединения строки удвоились ровно в два раза — почти всегда в правой таблице две записи на ключ связи. Проверьте её отдельным запросом с группировкой по полю связи и КОЛИЧЕСТВО(*): сразу увидите «виновные» ключи.
ПЗ
Практическое замечание

Дубли при объединении запросов: ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ

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

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

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

РАЗЛИЧНЫЕ

Убирает полностью идентичные строки. Просто, но не работает, если строки отличаются хотя бы одним полем.

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

Сворачивает строки по заданному ключу с агрегацией остальных полей. Гибче, но требует продумать агрегатные функции.

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

Устраняет первопричину размножения строк. Требует анализа данных, зато не искажает суммы.

ОБЪЕДИНИТЬ

Убирает дубли между частями объединения автоматически, но медленнее, чем ОБЪЕДИНИТЬ ВСЕ.

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

Самая надёжная проверка — контрольный запрос: сгруппируйте результат по ключевым полям и вычислите КОЛИЧЕСТВО(*). Если максимальное значение равно единице, дублей по этому ключу нет. В консоли запросов это делается за минуту без изменения основного кода.

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

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

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

Группировка результата по ключу с КОЛИЧЕСТВО(*)
Норма

Максимум равен 1 — дублей нет

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

Есть значения больше 1 — дубли остались

Сумма числового поля до и после устранения дублей
Норма

Сумма не изменилась или вернулась к значению без соединения

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

Сумма выросла — строки размножаются соединением

Число строк результата против левой таблицы
Норма

Количество совпадает или меньше ожидаемого

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

Строк стало больше, чем в исходной таблице

Типичные ошибки при удалении дублей

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

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

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

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

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

Частые вопросы

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

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

Что быстрее: РАЗЛИЧНЫЕ или СГРУППИРОВАТЬ ПО?

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

Как оставить только одну строку из нескольких похожих?

Сгруппируйте по ключевому полю и возьмите МАКСИМУМ или МИНИМУМ по признаку выбора — например, МАКСИМУМ по дате даст самую позднюю запись. Если нужна вся строка целиком, сначала найдите ключ нужной записи, затем соединитесь с исходной таблицей по этому ключу.

После левого соединения суммы задвоились — что делать?

Это признак связи «один ко многим»: в правой таблице несколько строк на ключ связи. Сверните правую таблицу вложенным запросом с группировкой до уровня ключа или используйте подходящую виртуальную таблицу (СрезПоследних, Остатки), либо уточните условие соединения дополнительными полями.

Чем ОБЪЕДИНИТЬ отличается от ОБЪЕДИНИТЬ ВСЕ?

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

Как в консоли запросов быстро найти, какая таблица даёт дубли?

Выполните правую таблицу отдельно с группировкой по полю связи и КОЛИЧЕСТВО(*) как поле. Отсортируйте результат по убыванию количества — ключи со значением больше единицы и есть источник размножения строк.