Как запросом найти дубликаты 1с

Skip to content

Как найти дубли в справочнике (элементы совпадающие по названию) при помощи запроса в 1С?
Для этого необходимо получить выборку из этого справочника с названием и ссылкой.

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

Например, как в этом запросе:

ВЫБРАТЬ
Товары.Наименование КАК Наименование,
КОЛИЧЕСТВО(Товары.Ссылка) КАК КоличествоДублей
ИЗ
Справочник.Товары КАК Товары

СГРУППИРОВАТЬ ПО
Товары.Наименование

ИМЕЮЩИЕ КОЛИЧЕСТВО(Товары.Ссылка) > 1

Результат его выполнения можно посмотреть на картинке ниже

Если Вы всё еще «плаваете» в конструкциях языка запросов, и у Вас вызывают трудности даже самые простые запросы, то рекомендую вам мой курс «Запросы в 1С от новичка до профи». Где эти и многие другие вопросы рассматриваются более подробно.

В чем особенность этого курса:
• Курс рассчитан на тех, кто не знаком с языком запросов в 1С;
• Учебный материал грамотно скомпонован и прост в освоении;
• Несколько десятков уроков;
• Полезные практические примеры;
• Все уроки изложены понятным и простым языком

Для моих читателей, купон на скидку 25%: hrW0rl9Nnx

Я стараюсь как можно чаще выпускать различные интересные бесплатные статьи и видеоуроки. Поэтому буду очень рад, если Вы поддержите мой проект перечислив любую сумму:

Можете перечислить любую сумму напрямую:
Яндекс.Деньги — 410012882996301
Web Money — R955262494655

Вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

Содержание:

1. Процесс поиска дублей в 1С, используя группировку

2. Поиск соединением таблиц в 1С

3. Поиск дублей как к4омбинации реквизитов

4. Использование библиотеки стандартных подсистем в типовых решениях 1С

ПОИСК ДУБЛЕЙ В 1С ЗАПРОСОМ

Данная тема не нова, но подобные вопросы периодически возникают у начинающих программистов. Здесь приведены примеры работающих запросов в 1С.

1. Процесс поиска дублей в 1С, используя группировку

Рис. 1 Группировки как средство поиска дублей в 1С
Рис. 1 Группировки как средство поиска дублей в 1С

Первый запрос выбирает ИНН, которые встречаются более 1 раза и помещает их в виртуальную таблицу 1С.

Во втором запросе находим тех контрагентов, ИНН которых входит в виртуальную таблицу 1С, и готовим вывод с удобной группировкой.

2. Поиск соединением таблиц в 1С

Рис. 2 Поиск дублей в 1С путем соединения таблиц
Рис. 2 Поиск дублей в 1С путем соединения таблиц

Несмотря на изящность решения, такой запрос выполняется гораздо дольше, чем с группировкой в 1С 8,3.

Даже вариация первого варианта с соединением таблиц 1С выполняется дольше.

Рис. 3 Поиск дублей соединением таблиц – не самый быстрый, но эффективный способ
Рис. 3 Поиск дублей соединением таблиц – не самый быстрый, но эффективный способ

Тем не менее, это работает.

3. Поиск дублей как комбинации реквизитов

Например, ищем контрагентов, имеющих одинаковые ИНН и КПП.

Рис. 4 Поиск дублей как комбинации одинаковых реквизитов в 1С
Рис. 4 Поиск дублей как комбинации одинаковых реквизитов в 1С

Идея, аналогична первому варианту. Создаем виртуальную таблицу, содержащую повторяющиеся пары ИНН/КПП. Отбираем Контрагентов, у которых пара значений ИНН/КПП встречается в виртуальной таблице 1С. Готовим удобный вывод, добавляя ИТОГИ. Поле Ключ создано для удобства вывода итоговых строк.

4. Использование библиотеки стандартных подсистем в типовых решениях 1С

В типовых решениях используется Библиотека стандартных подсистем, в которой присутствует подсистема «Поиск и удаление дублей ».

Чаще всего пользователи используют одноименную обработку данной подсистемы, которая размещена в «Администрирование» (или «НСИ и Администрирование») → Обслуживание → Корректировка данных → Поиск и удаление дублей 1С».

Кстати, обработка работает, если найдено не более 1500 дублей. Если дублей слишком много, то придется подправить код обработки 1С.

К функциям подсистемы можно обращаться и программно. Они расположены в общем модуле ПоискИУдалениеДублей . Например:

Рис. 5 Программное обращение к функциям подсистемы
Рис. 5 Программное обращение к функциям подсистемы

Специалист компании ООО «Кодерлайн» Иван Горбунов.

Содержание:

1.    Работа с консолью запросов

2.    Добавление поиска по производителю  

1.    Работа с консолью запросов

Цель данной статьи – помочь начинающим разработчикам немного лучше разобраться с таким важным аспектом программирования на платформе 1С 8.3 как запросы.

Разберем на простом примере, как с помощью такого инструмента как консоль запросов найти дублирующие друг друга записи в справочнике 1С 8.3. Согласитесь, ведь зачем перегружать справочник лишними элементами, если у нас уже есть элемент с такими реквизитами.

Пример будет показан на самой простой конфигурации 1С 8.3. За основу была взята учебная конфигурация, с помощью которой специалисты сдают экзамен. После чего в справочнике номенклатура был добавлен дополнительный реквизит «Производитель». Теперь откроем режим предприятия, добавим в справочник «Номенклатура» по три дубля двух наименований (причем у двух из них будет также совпадать и производитель).

Откроем консоль запросов и для начала напишем следующий текст:

В данном запросе происходит группировка выборки по названию, а к полю «Ссылка» применяете функцию «Количество» 1С.


Тем самым узнаем, сколько с таким названием элементов справочника.


Но нас не интересуют «одиночные» элементы, т.е. те названия у которых одна ссылка. Поэтому необходимо использовать оператор «Имеющие», который применяем к функции «Количество», ставя условие что результат и вывод функции больше одного. Таким образом мы получили по три номенклатуры с одинаковым наименованием. 

2.    Добавление поиска по производителю

Теперь попробуем немного усложнить запрос. Добавили поиск и по производителю. Все что нужно сделать, это добавить в выборку поле «Производитель», и так же как и с наименованием сгруппировать по этому полю. В итоге запрос 1С 8.3 будет выглядеть следующим образом:

Теперь выполним его и проверим полученный результат:

Таким образом можно построить и гораздо более сложные запросы для поиска дублей. Нужно всего лишь добавить в выборку новое поле и сгруппировать.

Специалист компании «Кодерлайн»

Айдар Фархутдинов

Запрос на поиск дублей

Я
   AlexeyVM

29.08.17 – 07:44

Добрый день!

Помогите пожалуйста разобраться с запросом.

Задача состоит в следующем. Мне надо проверить элементы выбранного справочника на наличие дублей по какому-нибудь конкретному полю (поле определяется из правил конвертации). Например – справочник “Номенклатура” синхронизация идет по полю “Код”. Мне нужно в виде дерева вывести все элементы справочника, у которых совпадает код. Пишу запрос, чтобы найти дубли по этому полю.

ВЫБРАТЬ
    СУММА(1) КАК КоличествоДублей,
    Номенклатура.Код
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.ЭтоГруппа = Ложь

СГРУППИРОВАТЬ ПО
    Номенклатура.Код

ИМЕЮЩИЕ
    СУММА(1) > 1

Выводит дублируемые элементы (их код).Как прицепить туда еще наименование, а лучше ссылку? И еще вопрос, как мне вывести запрос в виде дерева? Чтобы выглядело вот-так

Неуникальный код 1

      Элемент1          КодЭлемента1

      Элемент2          КодЭлемента2

      Элемент3          КодЭлемента3

На примере:

0000001

      Соль              0000001

      Сахар             0000001

0000002

      Мука              0000002

      Хлеб              0000002

   shadow_sw

1 – 29.08.17 – 07:46

выбрать различные с группировкой код/наименование

   AlexeyVM

2 – 29.08.17 – 07:51

Ой, запрос начальный выложил

ВЫБРАТЬ
    СУММА(1) КАК КоличествоДублей,
    Номенклатура.Код КАК Код
ПОМЕСТИТЬ ВТ_дубли
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.ЭтоГруппа = ЛОЖЬ

СГРУППИРОВАТЬ ПО
    Номенклатура.Код

ИМЕЮЩИЕ
    СУММА(1) > 1
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    Номенклатура.Код КАК Код,
    Номенклатура.Ссылка
ИЗ
    ВТ_дубли КАК ВТ_дубли
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
        ПО ВТ_дубли.Код = Номенклатура.Код

СГРУППИРОВАТЬ ПО
    Номенклатура.Ссылка,
    Номенклатура.Код

УПОРЯДОЧИТЬ ПО
    Номенклатура.Код
   AlexeyVM

3 – 29.08.17 – 07:54

(2) Результат запроса выводит

Соль  0000001
Сахар 0000001

А как сделать, чтобы было так:

0000001
    Соль  0000001
    Сахар 0000001
   rmil

4 – 29.08.17 – 07:55

ВЫБРАТЬ

    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Номенклатура.Ссылка) КАК КоличествоДублей,

    Номенклатура.Код КАК Код

……

ИТОГИ ПО

     Номенклатура.Код

   shadow_sw

5 – 29.08.17 – 07:56

(4) вот он сча скопирует и ничему не научится

   rmil

6 – 29.08.17 – 07:56

=)

   МимохожийОднако

7 – 29.08.17 – 07:58

Посмотри в УТ11 или БП3.0 обработку Поиск и замена дублей

   AlexeyVM

8 – 29.08.17 – 08:27

(4)

Не понял что это даст, это же просто выведет список кодов с их количеством в справочнике?

   AlexeyVM

9 – 29.08.17 – 08:44

Виноват, неправильно понял вначале, исправил

   Xapac

10 – 29.08.17 – 08:46

Выбрать ВСЕДУБЛИ(Номенклатура.Ссылка)

из

ИЗ

    Справочник.Номенклатура КАК Номенклатура

ГДЕ

    Номенклатура.ЭтоГруппа = Ложь

ничего придумывать не нужно

   Redkiy

11 – 29.08.17 – 08:53

Ему в дереве нужно, тогда так ВСЕДУБЛИВДЕРЕВО(Номенклатура.Ссылка)

   dezss

12 – 29.08.17 – 08:58

(2) тебе только добавить нужно

ИТОГИ ПО

    Номенклатура.Код

И все.

   dezss

13 – 29.08.17 – 09:00

(11) Ты забыл добавить

ВСЕДУБЛИВДЕРЕВОИМЕНЕМНУРАОИЕВА(Номенклатура.Ссылка)

   dezss

14 – 29.08.17 – 09:01

(13) +очипятка

ВСЕДУБЛИВДЕРЕВОИМЕНЕМНУРАЛИЕВА

   Heckfy

15 – 29.08.17 – 09:32

Эээ, стесняюсь спросить, а чем типовая обработка не подходит? Там очень хороший функционал.

   Chameleon1980

16 – 29.08.17 – 09:40

(15) дык ему просто запрос нужно, как я понял.

и дерево постоить

ИМХО правильный ответ – ключевое слово “итоги”

и параметры метода “Выгрузить” результата запроса.

  

AlexeyVM

17 – 29.08.17 – 12:08

(15) Потому что это в дальнейшем там придется все усложнить. В итоге должна получиться обработка, которая проверит сразу все справочники на наличие дублей по полям, по которым идет синхронизация справочника в правилах обмена. И далее в виде дерева покажет все неуникальные элементы справочников. Ну и там в дальнейшем еще некоторые мелочи

Проверка на наличие дублирующихся строк в табличных частях

Время прочтения – 7 мин.

Получить бесплатную консультацию

Думаю, каждый программист рано или поздно сталкивался с подобной задачей: как реализовать проверку на наличие дублирующихся строк в табличных частях. Кому-то просто нужно проверить: есть, или нет, дубли. Кому-то нужно известить пользователя, и сообщить ему номера строк с дублями. Это вопросы будут рассмотрены в данной статье. Но давайте сразу определимся с терминологией: поля, по которым будет осуществляться контроль, назовем «ключевые».


Итак, предположим, что у нас стоит задача проверить наличие дублей строк табличной части по ключевым полям. Пусть это будет документ «Реализация товаров, услуг», дубли строк мы будем искать в табличной части «Товары», а в качестве ключевых полей будем использовать следующие реквизиты табличной части: Качество, Номенклатура, Склад, СерияНоменклатуры и ХарактеристикаНоменклатуры.



Рассмотрим следующие ситуации:


1) Проверка на наличие дублирующихся строк на уровне есть/нет.
Реализация ее будет выглядеть следующим образом:

Запрос = Новый Запрос;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Запрос.Текст =
“ВЫБРАТЬ
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры,
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) КАК КоличествоДублей
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть
|ГДЕ
| ТабЧасть.Ссылка = &Ссылка
|
|СГРУППИРОВАТЬ ПО
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры
|
|ИМЕЮЩИЕ
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) > 1″;
РезЗапроса = Запрос.Выполнить();
Если Не РезЗапроса.Пустой() Тогда
              Сообщить(“Имеются дубли строк!!!”); 
КонецЕсли;

Здесь все достаточно просто. Обращаемся к данным табличной части документа, группируем по ключевым полям с использование агрегатной функции для подсчета количества номеров строк. Накладываем условие по вычисленному значению агрегатной функции. Все.

2) Классика жанра. Выведем в сообщении пользователю номера всех тех строк табличной части, которые являются дублями.

Запрос = Новый Запрос; 

Запрос.УстановитьПараметр(“Ссылка”, Ссылка); 

Запрос.Текст =
“ВЫБРАТЬ 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры, 
| ТабЧасть.НомерСтроки КАК НомерСтроки 
|ПОМЕСТИТЬ ВТ_ТабЧасть 
|ИЗ 
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть 
|ГДЕ 
| ТабЧасть.Ссылка = &Ссылка 
|; 
| |//////////////////////////////////////////////////////////////////////////////// 
|ВЫБРАТЬ 
| ТабЧасть.Качество КАК Качество, 
| ТабЧасть.Номенклатура КАК Номенклатура, 
| ТабЧасть.СерияНоменклатуры КАК СерияНоменклатуры, 
| ТабЧасть.Склад КАК Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры, 
| ТабЧасть.НомерСтроки КАК НомерСтроки 
|ИЗ 
| ВТ_ТабЧасть КАК ТабЧасть 
|ГДЕ 
| (ТабЧасть.Качество, ТабЧасть.Номенклатура, ТабЧасть.СерияНоменклатуры, ТабЧасть.Склад, ТабЧасть.ХарактеристикаНоменклатуры) В 
| (ВЫБРАТЬ 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИЗ 
| ВТ_ТабЧасть КАК ВТ 
| СГРУППИРОВАТЬ ПО 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИМЕЮЩИЕ 
| КОЛИЧЕСТВО(ВТ.НомерСтроки) > 1) 

|УПОРЯДОЧИТЬ ПО 
| НомерСтроки 
|ИТОГИ ПО 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад”;
РезЗапроса = Запрос.Выполнить(); 
Если Не РезЗапроса.Пустой() Тогда 
Выб_Качество = РезЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Качество.Следующий() Цикл 
Выб_Номенклатура = Выб_Качество.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Номенклатура.Следующий() Цикл 
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_СерияНоменклатуры.Следующий() Цикл 
Выб_Склад = Выб_СерияНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Склад.Следующий() Цикл 
Выборка = Выб_Склад.Выбрать(); 
ТекстСообщения = “”; 
Пока Выборка.Следующий() Цикл 
ТекстСообщения = ТекстСообщения + ?(ПустаяСтрока(ТекстСообщения), “”, “, “) + Выборка.НомерСтроки; 
КонецЦикла; 
ТекстСообщения = “Обнаружено дублирование строк: ” + ТекстСообщения; Сообщить(ТекстСообщения); 
КонецЦикла; 
КонецЦикла; 
КонецЦикла; 
КонецЦикла; 

КонецЕсли

Здесь все тоже не слишком сложно. Обратились к данным табличной части документа, поместили их во временную таблицу. Далее работаем со временной таблицей. Обращаемся к ней, отбираем те данные, по которым есть дубли (условие с использованием вложенного запроса). А далее, для того, чтобы сохранить все множество значений номеров строк, нам необходимо по ключевым полям объявить итоги. В таком случае в результате запроса, при использовании механизма итогов, появляются дополнительные строки, в которых хранится итог для того, или иного поля, а сам результат принимает иерархический вид, или вид дерева. Для того, чтобы вывести пользователю сообщение, нам нужно обойти результат запроса, и по каждому набору ключевых полей скомпоновать текст сообщения, и выдать его пользователю.


А теперь попробуем оценить перспективу доработки. Допустим, у нас изменился состав ключевых полей в сторону увеличения их количества: добавились ЕдиницаИзмерения и ЗаказПокупателя. Чтобы контроль дублей строк не перестал работать, нам нужно доработать запрос и обход результата запроса следующим образом:


Запрос = Новый Запрос; 
Запрос.УстановитьПараметр(“Ссылка”, Ссылка); 
Запрос.Текст = 
ВЫБРАТЬ
| ТабЧасть.ЕдиницаИзмерения, 
| ТабЧасть.ЗаказПокупателя, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры, 
| ТабЧасть.НомерСтроки КАК НомерСтроки 
|ПОМЕСТИТЬ ВТ_ТабЧасть 
|ИЗ 
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть 
|ГДЕ 
| ТабЧасть.Ссылка = &Ссылка 
|; 

|//////////////////////////////////////////////////////////////////////////////// 
|ВЫБРАТЬ 
| ТабЧасть.ЕдиницаИзмерения КАК ЕдиницаИзмерения, 
| ТабЧасть.ЗаказПокупателя КАК ЗаказПокупателя, 
| ТабЧасть.Качество КАК Качество, 
| ТабЧасть.Номенклатура КАК Номенклатура, 
| ТабЧасть.СерияНоменклатуры КАК СерияНоменклатуры, 
| ТабЧасть.Склад КАК Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры, 
| ТабЧасть.НомерСтроки КАК НомерСтроки 
|ИЗ 
| ВТ_ТабЧасть КАК ТабЧасть 
|ГДЕ 
| (ТабЧасть.ЕдиницаИзмерения, ТабЧасть.ЗаказПокупателя, ТабЧасть.Качество, ТабЧасть.Номенклатура, ТабЧасть.СерияНоменклатуры, ТабЧасть.Склад, ТабЧасть.ХарактеристикаНоменклатуры) В 
| (ВЫБРАТЬ 
| ВТ.ЕдиницаИзмерения, 
| ВТ.ЗаказПокупателя, 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИЗ 
| ВТ_ТабЧасть КАК ВТ 
| СГРУППИРОВАТЬ ПО 
| ВТ.ЕдиницаИзмерения, 
| ВТ.ЗаказПокупателя, 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИМЕЮЩИЕ 
| КОЛИЧЕСТВО(ВТ.НомерСтроки) > 1) 

|УПОРЯДОЧИТЬ ПО 
| НомерСтроки 
|ИТОГИ ПО 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры,
| Склад, 
| ХарактеристикаНоменклатуры, 
| ЕдиницаИзмерения”;
РезЗапроса = Запрос.Выполнить(); 
Если Не РезЗапроса.Пустой() Тогда 
Выб_Качество = РезЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Качество.Следующий() Цикл 
Выб_Номенклатура = Выб_Качество.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Номенклатура.Следующий() Цикл 
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_СерияНоменклатуры.Следующий() Цикл 
Выб_Склад = Выб_СерияНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Склад.Следующий() Цикл 
Выб_ХарактеристикаНоменклатуры = Выб_Склад.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_ХарактеристикаНоменклатуры.Следующий() Цикл 
Выб_ЕдиницаИзмерения=Выб_ХарактеристикаНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_ЕдиницаИзмерения.Следующий() Цикл 
ТекстСообщения = “”; 
Выборка = Выб_ЕдиницаИзмерения.Выбрать(); 
Пока

Подпишитесь на дайджест!

Подпишитесь на дайджест, и получайте ежемесячно подборку полезных статей.

3) Альтернативный вариант. 

Реализация предыдущего варианта другим способом. Предлагаю использовать особенность запросов 1С, позволяющих обращаться к данным табличных частей, как к обычным полям выборки. Ну все-таки не совсем обычным, но все же полям выборки. Кроме того, нам придётся использовать не самый оптимальный способ соединения данных – декартово произведение. Почему так – опишу ниже.

ШаблонОшибки = “Табличная часть ‘Товары’: по реквизитам ‘Качество, Номенклатура, СерияНоменклатуры, Склад, ХарактеристикаНоменклатуры’ обнаружено дублирование строк ‘%1′”; 
Запрос = Новый Запрос; 
Запрос.УстановитьПараметр(“Ссылка”, Объект.Ссылка); 
Запрос.Текст
ВЫБРАТЬ
| ТабЧасть.Ссылка, 
| МИНИМУМ(ТабЧасть.НомерСтроки) КАК МинНомерСтроки, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры 
|ПОМЕСТИТЬ ВТ_ТабЧасть 
|ИЗ 
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть 
|ГДЕ 
| ТабЧасть.Ссылка = &Ссылка 

|СГРУППИРОВАТЬ ПО 
| ТабЧасть.Ссылка, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры 
| |ИМЕЮЩИЕ 
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) > 1 
|; 

|//////////////////////////////////////////////////////////////////////////////// 
|ВЫБРАТЬ 
| ТабЧасть.Ссылка, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры, 
| Док.Товары.( 
| НомерСтроки, 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад, 
| ХарактеристикаНоменклатуры 
| ) КАК ДублиСтрок 
|ИЗ 
| (ВЫБРАТЬ 
| Док.Товары.( 
| НомерСтроки, 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад, 
| ХарактеристикаНоменклатуры 
| ) КАК Товары 
| ИЗ 
| Документ.РеализацияТоваровУслуг КАК Док 
| ГДЕ 
| Док.Ссылка = &Ссылка 
| И (Док.Товары.Качество, Док.Товары.Номенклатура, Док.Товары.СерияНоменклатуры, Док.Товары.Склад, Док.Товары.ХарактеристикаНоменклатуры) В 
| (ВЫБРАТЬ 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИЗ 
| ВТ_ТабЧасть КАК ВТ)) КАК Док 
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ТабЧасть КАК ТабЧасть 
| ПО (ИСТИНА) 
|ГДЕ 
| Док.Товары.Качество = ТабЧасть.Качество 
| И Док.Товары.Номенклатура = ТабЧасть.Номенклатура 
| И Док.Товары.СерияНоменклатуры = ТабЧасть.СерияНоменклатуры 
| И Док.Товары.Склад = ТабЧасть.Склад 
| И Док.Товары.ХарактеристикаНоменклатуры = ТабЧасть.ХарактеристикаНоменклатуры 

|УПОРЯДОЧИТЬ ПО 
| ТабЧасть.МинНомерСтроки, 
| Док.Товары.НомерСтроки”;
ТЗ_Результат = Запрос.Выполнить().Выгрузить(); 
Для Каждого СтрТЗ Из ТЗ_Результат Цикл 
Сообщить(СтрШаблон(ШаблонОшибки, СтрСоединить(СтрТЗ.ДублиСтрок.ВыгрузитьКолонку(“НомерСтроки”), “, “))); 
КонецЦикла;

Главное отличие от предыдущего варианта: обход результата запроса осуществляется линейным способом. Т.е. при изменении состава ключевых полей меняется только текст запроса.

Несколько комментариев по поводу запроса.

Работа с табличными частями в качестве полей выборки накладывает ряд ограничений на выполнение запросов. Во-первых, это работа с временными таблицами. Т.е. нельзя помещать такие объекты во временные таблицы, но никто не мешает использовать вложенные запросы. Во-вторых, это соединения таблиц. Мне требовалось написать такой запрос, который бы возвратил мне наборы ключевых полей по которым имеются дубли, и многострочный объект, содержащий все строки с таким же набором ключевых полей. Обычные соединения (ВНУТРЕННЕЕ, ЛЕВОЕ, ПРАВОЕ, ПОЛНОЕ) возвращают всю табличную часть, что, в общем, правильно – для части объекта условие соединения же выполняется? Выполняется. Ну тогда и получите всю табличную часть. Искомый результат, как оказалось, достигается декартовым произведением. Мне как-то претит видеть в тексте запроса перечисление таблиц через запятую, поэтому я все декартовы произведения всегда реализую через «… СОЕДИНЕНИЕ … ПО (ИСТИНА)». Чтобы ограничить мсье Декарта в аппетитах (и повысить производительность), применяются дополнительные ограничения.

Теперь о производительности. Производились тестовые замеры каждого из вариантов на документе с большим количеством строк в табличной части. Количество строк в тестируемом документе: 47 817, 4 комбинации ключевых полей с дублями по 2, 2, 3 и 4 строки. Результаты замеров:

Вариант 1) 0:00:00.078 сек.

Вариант 2) 0:00:00.265 сек.

Вариант 3) 0:00:01.513 сек.

Как видим, третий вариант, как и ожидалось, самый медленный, но он же является самым удобным в перспективе модификации.

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

1.png

1) Выбираем вид объекта: Документ или Справочник.

2) Выбираем тип объекта: Какой именно документ или справочник.

3) Выбираем табличную часть объекта.

4) Определяем состав ключевых полей в специальном диалоге

2.png

5) Если мы хотим, то можем указать ссылку на объект, чтобы проверить его на наличие дублей.

6) Если активен флажок «Сгенерировать и показать код для проверки на дубли», то будет сгенерирован программный код для выполнения проверки на дубли строк с имеющимися настройками.

Автор статьи:


Эксперт по технологическим вопросам ИнфоСофт

Добавить комментарий