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