При решении задач сверки данных, аудита нормативно-справочной информации (НСИ) или подготовки к инвентаризации часто возникает необходимость найти дублирующиеся записи в базе данных. Типичный пример — выявление позиций номенклатуры, для которых задано несколько разных штрихкодов, либо поиск штрихкодов, ошибочно привязанных к нескольким товарам.
Рассмотрим несколько эффективных способов построения запросов на платформе 1С:Предприятие для решения этой задачи: от простых группировок с условием на агрегатные функции до оптимальных двухэтапных запросов.
Самый прямой и лаконичный способ отфильтровать повторяющиеся данные — использовать секцию СГРУППИРОВАТЬ ПО совместно с условием ИМЕЮЩИЕ. В секции ИМЕЮЩИЕ проверяется условие, накладываемое на агрегатную функцию (например, количество записей больше единицы).
Разберем ситуацию, когда нам необходимо получить список ссылок на номенклатуру и их артикулы, у которых в регистре сведений зарегистрировано более одного штрихкода:
ВЫБРАТЬ
Штрихкоды.Номенклатура КАК НоменклатураСсылка,
Номенклатура.Артикул КАК Артикул,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) КАК КоличествоШтрихкодов
ИЗ
РегистрСведений.Штрихкоды КАК Штрихкоды
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО Штрихкоды.Номенклатура = Номенклатура.Ссылка
СГРУППИРОВАТЬ ПО
Штрихкоды.Номенклатура,
Номенклатура.Артикул
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) > 1
Обратите внимание: использование модификатора РАЗЛИЧНЫЕ внутри функции КОЛИЧЕСТВО гарантирует, что запрос посчитает именно уникальные штрихкоды. Если в регистре присутствуют записи с одинаковым штрихкодом, но разными дополнительными измерениями (например, характеристиками или упаковками), обычное КОЛИЧЕСТВО(*) учло бы строки таблицы, а не фактические дубли значений штрихкода.
Предыдущий вариант возвращает только свернутый список позиций и количество дублей. Однако на практике часто требуется вывести сами строки с каждым штрихкодом для последующего визуального анализа или программной обработки.
Посмотрим на пример запроса, который выводит все детальные записи только по тем позициям номенклатуры, которые имеют более одного штрихкода:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Артикул КАК Артикул,
Штрихкоды.Штрихкод КАК Штрихкод
ИЗ
Справочник.Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
ПО Номенклатура.Ссылка = Штрихкоды.Номенклатура
ГДЕ
Номенклатура.Ссылка В
(ВЫБРАТЬ
ШтрихкодыДубли.Номенклатура
ИЗ
РегистрСведений.Штрихкоды КАК ШтрихкодыДубли
СГРУППИРОВАТЬ ПО
ШтрихкодыДубли.Номенклатура
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ШтрихкодыДубли.Штрихкод) > 1)
УПОРЯДОЧИТЬ ПО
Номенклатура.Артикул
В этом запросе во вложенной выборке отбираются только идентификаторы товаров с дублями, а основная таблица связывается с регистром и выводит подробную информацию по каждому штрихкоду отобранных товаров.
Если база данных содержит сотни тысяч или миллионы записей, использование тяжелых вложенных запросов или неоптимизированных соединений может приводить к снижению производительности СУБД. В профессиональной разработке 1С рекомендуется разделять такие выборки на пакеты с применением временных таблиц.
Разберем по шагам создание оптимального пакетного запроса:
ВТ_ДублирующиеНоменклатуры.ВНУТРЕННЕЕ СОЕДИНЕНИЕ.
ВЫБРАТЬ
Штрихкоды.Номенклатура КАК НоменклатураСсылка
ПОМЕСТИТЬ ВТ_ДублирующиеНоменклатуры
ИЗ
РегистрСведений.Штрихкоды КАК Штрихкоды
СГРУППИРОВАТЬ ПО
Штрихкоды.Номенклатура
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Штрихкоды.Штрихкод) > 1
ИНДЕКСИРОВАТЬ ПО
НоменклатураСсылка
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Номенклатура.Ссылка КАК НоменклатураСсылка,
Номенклатура.Артикул КАК Артикул,
Номенклатура.Наименование КАК Наименование,
Штрихкоды.Штрихкод КАК Штрихкод
ИЗ
ВТ_ДублирующиеНоменклатуры КАК ВТ_Дубли
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО ВТ_Дубли.НоменклатураСсылка = Номенклатура.Ссылка
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
ПО ВТ_Дубли.НоменклатураСсылка = Штрихкоды.Номенклатура
УПОРЯДОЧИТЬ ПО
Номенклатура.Артикул
Проанализируем типичные ошибки, которые допускают разработчики при поиске повторяющихся строк:
Штрихкоды.Владелец.Артикул в секциях ВЫБРАТЬ или СГРУППИРОВАТЬ ПО заставляет платформу формировать неявное левое соединение. На больших объемах данных это замедляет выполнение запроса. Всегда соединяйте таблицы явно по ссылочным полям.ТаблицаЗначений.Свернуть() требует больших затрат оперативной памяти и работает медленнее, чем расчет агрегатов средствами СУБД.Артикул, убедитесь, что в метаданных справочника для этого реквизита включена индексация (свойство Индексировать).