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