Как в запросе 1С вывести только повторяющиеся строки и найти дублирующиеся штрихкоды?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При решении задач сверки данных, аудита нормативно-справочной информации (НСИ) или подготовки к инвентаризации часто возникает необходимость найти дублирующиеся записи в базе данных. Типичный пример — выявление позиций номенклатуры, для которых задано несколько разных штрихкодов, либо поиск штрихкодов, ошибочно привязанных к нескольким товарам.

Рассмотрим несколько эффективных способов построения запросов на платформе 1С:Предприятие для решения этой задачи: от простых группировок с условием на агрегатные функции до оптимальных двухэтапных запросов.

Способ 1. Использование группировки и конструкции ИМЕЮЩИЕ

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

Разберем ситуацию, когда нам необходимо получить список ссылок на номенклатуру и их артикулы, у которых в регистре сведений зарегистрировано более одного штрихкода:


ВЫБРАТЬ
    Штрихкоды.Номенклатура КАК НоменклатураСсылка,
    Номенклатура.Артикул КАК Артикул,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) КАК КоличествоШтрихкодов
ИЗ
    РегистрСведений.Штрихкоды КАК Штрихкоды
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
        ПО Штрихкоды.Номенклатура = Номенклатура.Ссылка
СГРУППИРОВАТЬ ПО
    Штрихкоды.Номенклатура,
    Номенклатура.Артикул
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) > 1

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

Способ 2. Вывод детальных строк дублей через подзапрос в секции ГДЕ

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

Посмотрим на пример запроса, который выводит все детальные записи только по тем позициям номенклатуры, которые имеют более одного штрихкода:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Артикул КАК Артикул,
    Штрихкоды.Штрихкод КАК Штрихкод
ИЗ
    Справочник.Номенклатура КАК Номенклатура
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
        ПО Номенклатура.Ссылка = Штрихкоды.Номенклатура
ГДЕ
    Номенклатура.Ссылка В
        (ВЫБРАТЬ
            ШтрихкодыДубли.Номенклатура
        ИЗ
            РегистрСведений.Штрихкоды КАК ШтрихкодыДубли
        СГРУППИРОВАТЬ ПО
            ШтрихкодыДубли.Номенклатура
        ИМЕЮЩИЕ
            КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ШтрихкодыДубли.Штрихкод) > 1)
УПОРЯДОЧИТЬ ПО
    Номенклатура.Артикул

В этом запросе во вложенной выборке отбираются только идентификаторы товаров с дублями, а основная таблица связывается с регистром и выводит подробную информацию по каждому штрихкоду отобранных товаров.

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

Если база данных содержит сотни тысяч или миллионы записей, использование тяжелых вложенных запросов или неоптимизированных соединений может приводить к снижению производительности СУБД. В профессиональной разработке 1С рекомендуется разделять такие выборки на пакеты с применением временных таблиц.

Разберем по шагам создание оптимального пакетного запроса:

  1. Сначала отбираем ссылки на номенклатуру, у которых зафиксировано несколько штрихкодов, и сохраняем результат во временную таблицу ВТ_ДублирующиеНоменклатуры.
  2. Индексируем временную таблицу по ключевому полю связи.
  3. Во втором пакете соединяем временную таблицу с основной номенклатурой и регистром штрихкодов с помощью ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

ВЫБРАТЬ
    Штрихкоды.Номенклатура КАК НоменклатураСсылка
ПОМЕСТИТЬ ВТ_ДублирующиеНоменклатуры
ИЗ
    РегистрСведений.Штрихкоды КАК Штрихкоды
СГРУППИРОВАТЬ ПО
    Штрихкоды.Номенклатура
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) > 1

ИНДЕКСИРОВАТЬ ПО
    НоменклатураСсылка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Номенклатура.Ссылка КАК НоменклатураСсылка,
    Номенклатура.Артикул КАК Артикул,
    Номенклатура.Наименование КАК Наименование,
    Штрихкоды.Штрихкод КАК Штрихкод
ИЗ
    ВТ_ДублирующиеНоменклатуры КАК ВТ_Дубли
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
        ПО ВТ_Дубли.НоменклатураСсылка = Номенклатура.Ссылка
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
        ПО ВТ_Дубли.НоменклатураСсылка = Штрихкоды.Номенклатура
УПОРЯДОЧИТЬ ПО
    Номенклатура.Артикул

Рекомендации по производительности и частые ошибки

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

  1. Разыменование полей через точку в группировках: обращение вида Штрихкоды.Владелец.Артикул в секциях ВЫБРАТЬ или СГРУППИРОВАТЬ ПО заставляет платформу формировать неявное левое соединение. На больших объемах данных это замедляет выполнение запроса. Всегда соединяйте таблицы явно по ссылочным полям.
  2. Поиск дублей через выгрузку в ТаблицуЗначений: выгрузка всего массива строк в память сервера с последующим методом ТаблицаЗначений.Свернуть() требует больших затрат оперативной памяти и работает медленнее, чем расчет агрегатов средствами СУБД.
  3. Отсутствие индексов: если группировка выполняется по реквизиту Артикул, убедитесь, что в метаданных справочника для этого реквизита включена индексация (свойство Индексировать).
← На главную