Имя: Пароль:
1C
 
Выборка уникальных значений и сравнение на двойные записи
0 EvgeniuXP
 
27.02.06
10:52
Алгоритм (тупой): Прохожу по всему регистру сведений хранящий все фио, заношу в таблицу значений, + к этому еще дата  рождения и ссылки на физлица. Затем выгружаю в другую таблицу значений, свертываю, получаю уникальные фио и дата рождения. Перебираю эту уникальные значения и смотрю, встречались ли они в общей таблице, если да, то нужно чтобы это было абсолютно два разных физлица, если это так, то этих сотрудников нужно объединить, т.к. это два физлица, хотя это один и тот же... бухгалтеры приняли два раза и не посмотрели, что он уже присутствовал...

Сделал так, но очень тормознуто работает, может выход есть получше?:
(весь регистр перебирает дольше, чем сам справочник, хотя элементов меньше, чем в справочнике физические лица)

   ТЗФИОДатаРожд=Новый ТаблицаЗначений();
   ТЗФИОДатаРожд.Колонки.Добавить("ФИО");
   ТЗФИОДатаРожд.Колонки.Добавить("ДатаРождения");
   ТЗФИОДатаРожд.Колонки.Добавить("ФизЛицо");
   
   // Получаем таблицу значений, которая хранит все "ФИО,ДатаРождения,ФизЛицо"
   Кол=0;
   Выборка=РегистрыСведений.ФИОФизЛиц.Выбрать();
   Пока Выборка.Следующий() Цикл
       ФизЛицо=Выборка.ФизЛицо;
       НоваяСтрока=ТЗФИОДатаРожд.Добавить();
       Если ФизЛицо.Пол.Наименование="Мужской" Тогда
           НоваяСтрока.ФИО=Выборка.Фамилия+" "+Выборка.Имя+" "+Выборка.Отчество;
       Иначе
           НоваяСтрока.ФИО=Выборка.Имя+" "+Выборка.Отчество;
       КонецЕсли;
       НоваяСтрока.ДатаРождения=ФизЛицо.ДатаРождения;
       НоваяСтрока.ФизЛицо=ФизЛицо;
       Кол=Кол+1;
       Если Кол%100=0 Тогда
           Состояние("Тестирование_00"+НО+": Пройдено по регистрам сведений ФИОФизЛиц: "+Кол);
       КонецЕсли;
   КонецЦикла;
   
   Состояние("Тестирование_00"+НО+": Ждите...");
   // Вторая таблица хранит уникальные "ФИО,ДатаРождения"
   ТЗУникальныеФИОДатаРождения=ТЗФИОДатаРожд.Скопировать();
   ТЗУникальныеФИОДатаРождения.Свернуть("ФИО,ДатаРождения");
   
   // Перебираем уникальные записи в одной таблице и ищем во второй таблице на двойные записи разных физлиц
   Кол=0;
   Для Индекс=0 По ТЗУникальныеФИОДатаРождения.Количество()-1 Цикл
       УникальноеФИОДатаРождение=ТЗУникальныеФИОДатаРождения[Индекс];
       Отбор=Новый Структура("ФИО,ДатаРождения");
       Отбор.ФИО=УникальноеФИОДатаРождение.ФИО;
       Отбор.ДатаРождения=УникальноеФИОДатаРождение.ДатаРождения;
       Строки=ТЗФИОДатаРожд.НайтиСтроки(Отбор);
       Если Строки.Количество()>1 Тогда
           Для Индекс1=0 По Строки.Количество()-2 Цикл
               Для Индекс2=Индекс1+1 По Строки.Количество()-1 Цикл
                   ФизЛицо1=Строки[Индекс1].ФизЛицо;
                   ФизЛицо2=Строки[Индекс2].ФизЛицо;
                   Если ФизЛицо1<>ФизЛицо2 Тогда
                       ЗанестиВСпрНеразобранныеДанные(НО,ФизЛицо1,ФизЛицо2);
                   КонецЕсли;
               КонецЦикла;
           КонецЦикла;
       КонецЕсли;
       Кол=Кол+1;
       Если Кол%100=0 Тогда
           Состояние("Тестирование_00"+НО+": Пройдено по уникальным ФИОДатаРождения: "+Кол);
       КонецЕсли;
   КонецЦикла;
1 АперБот
 
27.02.06
11:37
Я иногда пропускаю утонувшие ветки, но эту заметил. Такая моя работа.
2 NuiNu
 
27.02.06
16:31
Никогда не сталкивался с такой задачей :(.

Навскидку.
В первой ТЗ поле "Флаг" типа число. При заполнении кладем туда 1. Свернул, если во "флаге" больше 1, значит повторяются ну а дальше че надо.
Не надо 2-й ТЗ ну и ...
Уверен, тоже неоптимальный алгоритм.
3 Широкий
 
27.02.06
16:36
В запросе сделай левое соединение - найдет все дубликаты -будет быстрее
Пример


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

УПОРЯДОЧИТЬ ПО
   Наименование
4 Mort
 
27.02.06
16:41
(3) Кажется просто выберет весь справочник.
5 Mort
 
27.02.06
16:42
Тут поднимался подобный вопрос:
v8: Конкурс на самый лучший алгоритм
6 Широкий
 
27.02.06
16:47
(4) Напугал... стал тестить обработку где используется :)) Нет, все нормально
7 dimoff
 
27.02.06
17:10
В запросе добавить поле со значением 1 и добавить поле Итогов, по прохождении верхнего уровня еслив  итогах больше 1, то выбираем детальные записи
8 dimoff
 
27.02.06
17:11
добавить поле итогов = добавить секцию итогов
9 EvgeniuXP
 
04.03.06
17:30
сделал по другому, два запроса, один уникальные собирает, второй все.
Выгружаем уникальные в ТЗ1, все записи в ТЗ2. Перебираем ТЗ1 и находим строки в ТЗ2, создаем ТЗ3 и заносим выбранные строки, свертываем по ФизЛицу, если кол-во больше двух - это двойные записи и в конце цикла УДАЛЯЮ пройденные строки из ТЗ2. Работает быстро, 1 минута на 17 тысяч сотрудников :))), не то что в 7.7...
Очень скорость увеличивается (после 3 тысяч уже заметно начинается, в конце черезчур быстро цифры летят), если в ТЗ2 (общая таблица) удалять уже пройденныые строки
10 EvgeniuXP
 
04.03.06
17:33
левым соединением, все-равно не понял...
Так как мужской пол
ФИО = Фамилия+Имя+Отчество+ДатаРождения.
Женский пол
ФИО = Имя+Отчество+ДатаРождения

В запросе нельзя объединить строки:
ФИО=Фамилия+Имя+Отчество+ДатаРождения
ФИО=Имя+Отчество+ДатаРОждения :(  и левое соединение не подходит...
11 EvgeniuXP
 
04.03.06
17:36
и кстати, заметил, запросы на много быстрее работают, за две секунды любая моя выборка... только вот запись справочников хромает сильно... очень долго... может там как-то можно одним потоком писать? транзакция не помогает... по крайней мере для PIV 3.0E...
12 EvgeniuXP
 
09.03.06
08:20
все получилось :), вместо одной минуты теперь три секунды :), а на 77 около 10-15 минут перебирал...
13 Гламурный Подонок
 
09.03.06
08:26
Можно и на 80 минут 40 перебирать. Только одному не справиться - помощник нужен...