Удаление дублей запросом

03.04.14

Разработка - Запросы

Удаляем дубли запросом (из его временной таблицы). Дубли определяем по набору полей сверки. Процедура для обычных форм.

Иногда возникает необходимость убрать дубли из результата запроса. Причём делать это хочется при помощи запроса - так быстрее (критично на больших объёмах данных).

Дубли имеются в виду частичные - т.е. это такие записи, где значения, скажем, по 3 полям совпадают (у двух или более записей), а по остальным полям - нет. Я назвал такие совпадающие поля условно "поля сверки дублей". В общем-то, их может быть сколько угодно - не обязательно именно 3.

Я написал процедуру, убирающую дубли запросом. Она принимает на входе временную таблицу запроса, из которой надо удалить дубли, список полей сверки дублей. Результат помещается в новую временную таблицу того же запроса. Опционально она может показать найденные дубли (и даже вывести их на экран в печатной таблице). Вот код этой процедуры:

Она проверена в 1С:Бухгалтерия 2.5, в ЗУП, возможно, потребуется исправить "ОбщегоНазначения" на "ОбщегоНазначенияЗК".

// Процедура удаления дублей из временной таблице запроса (только для обычных форм).

// Параметры:

// "Запрос" - запрос, содержащий временную таблицу, из которой надо удалить дубли.

// "ИмяВТВход" - имя временной таблицы запроса, из которой надо удалить дубли. Удаляется после проработки процедуры (как более не нужная).

// "ПоляСверкиДубля" - строка вида "Поле1,Поле2,Поле3", содержащая имена тех полей из "ИмяВТВход", по которым мы будем искать дубли.

// "ИмяВТВыход" - имя временной таблицы запроса, в которую помещается результат работы процедуры - т.е. "ИмяВТВход", откуда убрали все дубли.

// "ОставитьВТДубли" - оставить или нет временную таблицу с обнаруженными дублями после проработки процедуры. 

// "ПоказыватьДубли" - выводить или нет печатную таблицу с обнаруженными дублями.

// "ЗаголовокТаблицыДублей" - заголовок для печатной таблицы "ПоказыватьДубли".

Процедура УдалитьДублиВТ(Запрос, ИмяВТВход, ПоляСверкиДубля, ИмяВТВыход, ОставитьВТДубли = Ложь, ПоказыватьДубли = Ложь, ЗаголовокТаблицыДублей = "Таблица найденных дублей")
	//Прототип: http://www.forum.mista.ru/topic.php?id=550537
	
	МПСД = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(ПоляСверкиДубля,",");
	
	ПоляЗапроса = "";
	
	ПоляСоединения = "";
	
	Для каждого Элем Из МПСД Цикл
		
		ПоляЗапроса = ПоляЗапроса + ИмяВТВход + "." + Элем + ", ";
		
		ПоляСоединения = ПоляСоединения + "(" + ИмяВТВход + "." + Элем + " = " + "ВТ_ДУБЛИ1." + Элем + ") И ";
	
	КонецЦикла;
	
	ПоляЗапроса = Лев(ПоляЗапроса, СтрДлина(ПоляЗапроса)-2);
	
	ПоляСоединения = Лев(ПоляСоединения, СтрДлина(ПоляСоединения)-3);
	
	Запрос.Текст = "ВЫБРАТЬ СУММА(1) КАК КоличествоДублей, " + ПоляЗапроса + " ПОМЕСТИТЬ ВТ_ДУБЛИ ИЗ " + ИмяВТВход + " КАК " + ИмяВТВход + 
	" СГРУППИРОВАТЬ ПО " + ПоляЗапроса + " ИМЕЮЩИЕ СУММА(1) > 1 ; ВЫБРАТЬ ВТ_ДУБЛИ.*, 1 КАК СтрокаДубля ПОМЕСТИТЬ ВТ_ДУБЛИ1 ИЗ ВТ_ДУБЛИ КАК ВТ_ДУБЛИ; ";
	
	Запрос.Текст = Запрос.Текст + "ВЫБРАТЬ " + ИмяВТВход + ".*, ЕСТЬNULL(ВТ_ДУБЛИ1.СтрокаДубля,0) КАК СтрокаДубля ПОМЕСТИТЬ ВТ_ВЫХОД ИЗ " + ИмяВТВход + " КАК " + ИмяВТВход +
	" ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДУБЛИ1 КАК ВТ_ДУБЛИ1 ПО " + ПоляСоединения + " ГДЕ ВТ_ДУБЛИ1.СтрокаДубля ЕСТЬ NULL";
	
	Запрос.Выполнить();
	
	Если ПоказыватьДубли Тогда
		
		ДанныеТаблицы = Новый Запрос;
		ДанныеТаблицы.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц;
		ДанныеТаблицы.Текст =
		"Выбрать 0 КАК НомерСтроки, *
		|    Из ВТ_ДУБЛИ
		|";
		
		ТЗДубли = ДанныеТаблицы.Выполнить().Выгрузить();
		
		Для Сч = 0 По ТЗДубли.Количество()-1 Цикл
			
			ТЗДубли[Сч].НомерСтроки = Сч + 1;
		
		КонецЦикла;
		
		Построитель=Новый ПостроительОтчета(); 
		Построитель.ИсточникДанных=Новый ОписаниеИсточникаДанных(ТЗДубли); 
		Построитель.ТекстЗаголовка = ЗаголовокТаблицыДублей;
		Построитель.Вывести();
		
	КонецЕсли; 
	
	ДанныеТаблицы = Новый Запрос;
	ДанныеТаблицы.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц;
	ДанныеТаблицы.Текст =
	"Выбрать ПЕРВЫЕ 1 *
	|    Из ВТ_ВЫХОД
	|";
	
	ТЗВыход = ДанныеТаблицы.Выполнить().Выгрузить();	
	
	ПоляЗапроса = "";
	
	Для каждого Колонка Из ТЗВыход.Колонки Цикл
		
		Если Колонка.Имя <> "СтрокаДубля" Тогда
			
			ПоляЗапроса = ПоляЗапроса + Колонка.Имя + ", ";
		
		КонецЕсли;
	
	КонецЦикла; 
	
	ПоляЗапроса = Лев(ПоляЗапроса, СтрДлина(ПоляЗапроса)-2);
	
	Запрос.Текст = "ВЫБРАТЬ " + ПоляЗапроса + " ПОМЕСТИТЬ " + ИмяВТВыход + " ИЗ ВТ_ВЫХОД; УНИЧТОЖИТЬ " + ИмяВТВход + 
	"; УНИЧТОЖИТЬ ВТ_ВЫХОД; УНИЧТОЖИТЬ ВТ_ДУБЛИ1";
	
	Если НЕ ОставитьВТДубли Тогда
		
		Запрос.Текст = Запрос.Текст + "; УНИЧТОЖИТЬ ВТ_ДУБЛИ";
	
	КонецЕсли;
	
	Запрос.Выполнить();	
	
КонецПроцедуры

Удаление дублей запросом

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта 1С v8.3 Управляемые формы Запросы Система компоновки данных Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

15500 руб.

02.09.2020    196579    1085    409    

1006

Инструментарий разработчика Запросы Программист 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

QueryConsole1C — расширение, включающее консоль запросов с поддержкой исполняемых представлений — аналогов виртуальных таблиц, основанных на методах программного интерфейса ЗУП. Оно позволяет выполнять запросы с учётом встроенной бизнес-логики, отлаживать алгоритмы получения данных и автоматически генерировать код на встроенном языке 1С.

1 стартмани

16.05.2025    3328    73    zup_dev    15    

57

Инструментарий разработчика Запросы Программист 1С v8.3 Управляемые формы 1С:ERP Управление предприятием 2 Абонемент ($m)

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

2 стартмани

05.03.2025    2882    10    XilDen    12    

23

Обновление 1С Запросы Программист 1С v8.3 1С:ERP Управление предприятием 2 Абонемент ($m)

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

2 стартмани

06.02.2025    2802    22    XilDen    26    

36

Запросы Программист 1С v8.3 Запросы 1C:Бухгалтерия Бесплатно (free)

В статье приведена удобная возможность отладки исполняемого запроса динамического списка.

03.12.2024    6881    artemusII    11    

24

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    14914    sergey279    18    

68

Запросы Программист 1С v8.3 Запросы 1C:Бухгалтерия Бесплатно (free)

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

11.10.2024    9580    XilDen    38    

101

СКД Механизмы типовых конфигураций Запросы Программист 1С v8.3 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Россия Бесплатно (free)

Работая с типовыми отчетами в конфигурациях «Зарплата и управление персоналом, редакция 3», «Зарплата и кадры государственного учреждения, редакция 3» и подобных, в схемах компоновки данных можно встретить конструкции запросов, которые обращаются к некоторым виртуальным таблицам.

20.08.2024    3947    PROSTO-1C    0    

26
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. mikhailovaew 127 14.04.14 16:27 Сейчас в теме
зачем так сложно? если дубли не нужны, пишем ВЫБРАТЬ РАЗЛИЧНЫЕ
Alex Star; +1 Ответить
2. prodines 107 17.04.14 15:41 Сейчас в теме
(1) mikhailovaew, в этом случае будут убраны лишь дублирующиеся записи, а дубли - нет. Это разные вещи.

Дубль - это множество записей с одинаковыми полями сверки, всегда содержащее как минимум 2 элемента (на то они и есть дубли, что их больше одного). Дублей в выборке может быть сколько угодно.

Ваш вариант в каждом дубле оставит одну запись, а остальные (дублирующиеся) уберёт. Мой вариант в каждом дубле не оставит ни одной записи.
Оставьте свое сообщение