|
Поиск (и удаление) не повторяющихся значений в таблице... | ☑ | ||
---|---|---|---|---|
0
new_hope
30.10.19
✎
15:16
|
Прошу, может кто знает действующий (и быстрый :-) алгоритм. Задача - ОСТАВИТЬ таблице (значений) те строки, которые повторяются два и более раз (то-есть удалить те строки, у которых нет повторов).
Поиск нужно осуществлять по 2-м колонкам из множества колонок. |
|||
1
Beduin
30.10.19
✎
15:17
|
Свернуть
|
|||
2
vicof
30.10.19
✎
15:20
|
Формировать таблицу изначально нужно правильно, чтобы потом не заниматься всякой фигней
|
|||
3
Garykom
гуру
30.10.19
✎
15:24
|
(0) Как это ни странно но данная задача лучше всего решается через запросы
|
|||
4
Garykom
гуру
30.10.19
✎
15:25
|
(3)+ Засовываешь ТЗ в запрос и соединяешь с собой внутренним соединением по нужным колонкам.
Причем чтобы исключить дубли (строка сама с собой) добавить условие на номер строки например. |
|||
5
new_hope
30.10.19
✎
15:27
|
(2) (3) Пытался разобраться через ЗАПРОС - но у меня из 4-х колонок в 3-х колонках ссылки не смог разобраться, так как ссылки не группируются. Короче - недостаточно знаний. Если есть готовый пример - ткните ссылку. Спасибо.
|
|||
6
new_hope
30.10.19
✎
15:29
|
(4) Мне дубли как раз нужно ВКЛЮЧАТЬ а не исключать. То что НЕ дублируется - вообще удалить (игнорировать) в результате
|
|||
7
Garykom
гуру
30.10.19
✎
15:31
|
(6) У меня все правильно написано, именно только дубли и выберутся в результате запроса.
|
|||
8
vicof
30.10.19
✎
15:36
|
(0) Зачем ты это хочешь сделать?
|
|||
9
new_hope
30.10.19
✎
15:40
|
(8) т.к. это ошибочные значения и нужно знать о них и перейти по наборам ссылок этих значений
|
|||
10
Йохохо
30.10.19
✎
15:42
|
(9) ну и бахни, НайтиСтроки, давно не удаляли строк из ТЗ
|
|||
11
azernot
30.10.19
✎
15:48
|
Выбрать КОлонка1, Колонка2, 1 как КоличествоСтрок
Поместить ЗначенияКолонок Из ТЗ ; Выбрать КОлонка1, Колонка2, Сумма(КОличествоСтрок) Поместить ПовторяющиесяКлючевыеКолонки Из ЗначенияКолонок Сгрупппировать по КОлонка1, Колонка2 Имеющие Сумма(КОличествоСтрок)>1 ; Выбрать * из ТЗ Внутреннее соединение ПовторяющиесяКлючевыеКолонки по ТЗ.Колонка1= ПовторяющиесяКлючевыеКолонки.Колонка1 И ТЗ.Колонка2= ПовторяющиесяКлючевыеКолонки.Колонка2 |
|||
12
new_hope
30.10.19
✎
15:49
|
(10) Так и думаю. Боюсь за скорость. Уверен, это можно сделать изящно запросом, но ума не хватает. :-(
Есть колонки "Документ1Ссылка, Документ2Ссылка, Документ3Ссылка, Дата, Фамилия" Так вот, нужно в результате оставить все значения, которые ИМЕЮТ дубли по полям "Дата и Фамилия". и дата и номер - значения НЕ уникальные. |
|||
13
Йохохо
30.10.19
✎
15:49
|
(11) а типизировать?)
|
|||
14
pechkin
30.10.19
✎
15:50
|
можно без запроса. в 1 проход. просто проверять, что след строка не такая же и пред была не такая.
значит эта строка единственная. тз вначале нужно отсортировать |
|||
15
pechkin
30.10.19
✎
15:51
|
ну или след строка такая же - добавляем строу в новую тз
|
|||
16
azernot
30.10.19
✎
15:54
|
(13) В запросе можно использовать только ТЗ с типизованными колонками. Так что ничего типизировать не надо. Или я не понимаю о чём ты...
|
|||
17
mistеr
30.10.19
✎
15:55
|
Сомневаюсь, что запросом всегда будет быстрее. Я бы сделал через Свернуть() и НайтиСтроки().
|
|||
18
Garykom
гуру
30.10.19
✎
15:57
|
(14) (15) Слегка подумай, надо выбрать все строки (со всеми их колонками) имеющие дубли по двум колонкам.
Условие выбора задолбаешься придумывать, в отличие от запроса. Тебе же надо выбрать и когда 2 и когда 3 и когда 4 строки и т.д. подряд имеют те же значения в паре колонок. Причем не пропустить и не накопировать лишнего в новую ТЗ. |
|||
19
D_E_S_131
30.10.19
✎
15:57
|
(12) Кинул свою ТЗ в запрос во временную таблицу. Соединил саму с собой по нужным полям (Дата и Фамилия). Поставил условие на поле из "дублирующей таблицы" "Есть НЕ Null".
|
|||
20
Garykom
гуру
30.10.19
✎
15:58
|
(17) А вот это уже более разумный вариант но тормозной, так как сначала свертка а потом поиск в цикле по свернутым.
|
|||
21
Garykom
гуру
30.10.19
✎
15:58
|
(19) см (4)
|
|||
22
azernot
30.10.19
✎
16:00
|
(19) Такой план всегда будет возвращать всю исходную ТЗ. :)
|
|||
23
Garykom
гуру
30.10.19
✎
16:00
|
(0) ТС выложи плиз тестовую табличку если не секретно, кому интересно на разных методах сможет потестить скорость.
|
|||
24
Garykom
гуру
30.10.19
✎
16:00
|
(22) Угу условие забыл исключения пар строк с самой собой, я предложил по номеру строки условие
|
|||
25
azernot
30.10.19
✎
16:00
|
+(22) нужно какое-то поле, позволяющие различать строки.. Типа "НомерСтроки". И ставить условие соединения по неравенству этого поля.
|
|||
26
mistеr
30.10.19
✎
16:07
|
(20) Не очевидно, что тормозной. На малых объемах не ощутимо, а на больших хз, нужно тестировать. Данные не гоняются на скуль и обратно, индексирование может помочь, в общем не очевидно.
|
|||
27
pechkin
30.10.19
✎
16:12
|
(18) ничего сложного нет.
классическая задача на именно программирование |
|||
28
Garykom
гуру
30.10.19
✎
16:12
|
(26) Проще тогда отсортировать, затем одним циклом проверять пары строк и находить начало и конец блока дубля строк.
Ну и имея эти пары НачальнаяСтрока, КонечнаяСтрока получить эти строки. или вариация с накопителем, куда строки в цикле добавляются если равна следующая или если следующая строка не равна то если в накопителе >=2 строки их в новую ТЗ добавляем, а накопитель очищаем и т.д. |
|||
29
pechkin
30.10.19
✎
16:14
|
(28) ну тоже самое описал, про что я говорил в (15)
|
|||
30
azernot
30.10.19
✎
16:14
|
(17) Зачем сворачивать?
Можно сделать в один цикл по ТЗ, с последующим удалением лишних МасивСтрокКУдалению = Новый Массив(); ТЗКлючевыхПолей = Новый ТаблицаЗначений; ТЗКлючевыхПолей.Колонки.Добавить("Колонка1", ТЗ.Колонки.найти("КОлонка1").ТипЗначения); ТЗКлючевыхПолей.Колонки.Добавить("Колонка2", ТЗ.Колонки.найти("КОлонка2").ТипЗначения); ТЗКлючевыхПолей.Колонки.Добавить("ПерваяСтрокаТЗ"); Для каждого СтрокаТЗ из ТЗ Цикл НайденныеСтроки = ТЗКлючевыхПолей.НайтиСтроки(Новый Структура("Колонка1, Колонка2", СтрокаТЗ.Колонка1, СтрокаТЗ.Колонка2); Если НайденныеСтроки.Количество()>0 ТОгда //Такие значения полей ранее уже встречались ИндексСтроки = МасивСтрокКУдалению.Найти(НайденныеСтроки[0].ПерваяСтрокаТЗ); Если НЕ ИндексСтроки = Неопределено ТОгда //Если первая строка с такими ключевыми полями числится к удалению, нужно убрать её оттуда МасивСтрокКУдалению.Удалить(ИндексСтроки); КонецЕсли; Продолжить; КОнецЕсли; //Сюда попадает только строка с ранее не встречающющимися значениями ключевых полей НоваяСтрокаКЛючевыхПолей = ТЗКлючевыхПОлей.Добавить(); ЗаполнитьЗначенияСвойств(НоваяСтрокаКЛючевыхПолей, СтрокаТЗ); НоваяСтрокаКЛючевыхПолей.ПерваяСтрокаТЗ = СтрокаТЗ; МасивСтрокКУдалению.Добавить(СтрокаТЗ); КонецЦикла; Для каждого УдаляемаяСтрока Из МасивСтрокКУдалению Цикл ТЗ.Удалить(УдаляемаяСтрока); КонецЦикла; |
|||
31
Garykom
гуру
30.10.19
✎
16:16
|
(29) Ты упустил важную вещь про буфер, твой алгоритм правильно только для пар дубль строк а если их там триплеты и более не сработает.
|
|||
32
pechkin
30.10.19
✎
16:16
|
(31) почему? достаточно счетчик добавить. буфер не нужен
|
|||
33
Garykom
гуру
30.10.19
✎
16:16
|
(30) Запросом сильно короче выглядит чем вот это длинное
|
|||
34
Garykom
гуру
30.10.19
✎
16:17
|
(32) Два счетчика тогда
|
|||
35
azernot
30.10.19
✎
16:18
|
(33) Зато без передачи данных с сервера приложений на сервер баз данных и наоборот.
|
|||
36
pechkin
30.10.19
✎
16:19
|
(34) не нужно.
предыдущую строку добавляем.если они совпадает с текущей. текущую добавляем, если счетчик > 1 при смене строки сбарсываем счетчик |
|||
37
azernot
30.10.19
✎
16:19
|
+(35) Хотя, может я неверно понимаю механизм запросов и в данном случае он не будет обращаться к серверу баз данных. Но почему-то я думаю, что это не так.
|
|||
38
mistеr
30.10.19
✎
16:23
|
(30) Сворачивать для того, чтобы не делать циклы по всей ТЗ.
|
|||
39
new_hope
30.10.19
✎
16:23
|
(23) А как выложить? Это не типовая конфа и как мне ссылки на документы выложить? Саму структуру таблички я указал (в реальной жизни вместо "Фамилия" - Строка с буквенно-цифровым значением :-)
|
|||
40
Ёпрст
30.10.19
✎
16:24
|
(30) можно сделать еще проще, достаточно отсортировать тз по ключевым полям и дальше сравнение строк с предыдущей.
Тогда НайтиСтроки в цикле не надо делать |
|||
41
Garykom
гуру
30.10.19
✎
16:27
|
(39) Табличку екселя или csv файлик с данными колонок можно выкладывать
|
|||
42
Garykom
гуру
30.10.19
✎
16:28
|
(40) Угу см (28)
|
|||
43
Креатив
30.10.19
✎
16:34
|
Присоединяюсь к тем ораторам, что за сортировку по ключевым полям и последующее сравнение строк.
Единственно добавлю, что обход нужно делать снизу таблицы, чтобы при удалении строк что-нибудь не пошло не так. Не факт, что будет быстро, зато очень прозрачно. |
|||
44
new_hope
30.10.19
✎
16:34
|
(23)
Номер Док_1 Док_2 Док_3 Дата Фамилия 1 Документ_Тип1_Номер_1 Документ_Тип2_Номер_1 Документ_Тип3_Номер_1 01.01.2019 Вася 2 Документ_Тип1_Номер_2 Документ_Тип2_Номер_2 Документ_Тип3_Номер_2 01.01.2019 Вася 3 Документ_Тип1_Номер_3 Документ_Тип2_Номер_3 Документ_Тип3_Номер_3 02.01.2019 ВАСЯ 4 Документ_Тип1_Номер_2 Документ_Тип2_Номер_1 Документ_Тип3_Номер_2 02.01.2019 Петя 5 Документ_Тип1_Номер_3 Документ_Тип2_Номер_2 Документ_Тип3_Номер_3 02.01.2019 Петя 6 Документ_Тип1_Номер_2 Документ_Тип2_Номер_1 Документ_Тип3_Номер_2 03.01.2019 ВАСИЛИЙ 7 Документ_Тип1_Номер_3 Документ_Тип2_Номер_2 Документ_Тип3_Номер_2 03.01.2019 Таня 8 Документ_Тип1_Номер_3 Документ_Тип2_Номер_3 Документ_Тип3_Номер_2 03.01.2019 Таня 9 Документ_Тип1_Номер_2 Документ_Тип2_Номер_1 Документ_Тип3_Номер_3 03.01.2019 НИКОЛАЙ 10 Документ_Тип1_Номер_3 Документ_Тип2_Номер_2 Документ_Тип3_Номер_2 04.01.2019 Жора 11 Документ_Тип1_Номер_2 Документ_Тип2_Номер_3 Документ_Тип3_Номер_3 04.01.2019 Жора 12 Документ_Тип1_Номер_3 Документ_Тип2_Номер_1 Документ_Тип3_Номер_2 04.01.2019 Жора Из этой таблицы должны бать УДАЛЕНЫ строки 3,6,9 (или быраны без них) так как нету дублей по колонкам "Дата и Фамилия". В Колонках Док_х могут быть любые ссылки на документы, хоть на все одинаковые. |
|||
45
MetaDon
30.10.19
✎
16:36
|
сортировать не надо; начиная с конечной строки проходим вверх, сравниваем колонки, если дубля не нашли (дошли до 1) - конечную строку удаляем;)
|
|||
46
Креатив
30.10.19
✎
16:44
|
(45)Возможно ты и прав n*(n-1)/2 сравнений. При сортировке может оказаться больше.
|
|||
47
mistеr
30.10.19
✎
17:13
|
Решение без сортировки и без циклов по всей таблице.
// Тестовые данные Запрос = Новый Запрос(" |ВЫБРАТЬ | ПриходныйКассовыйОрдер.Ссылка, | ПриходныйКассовыйОрдер.Организация, | ПриходныйКассовыйОрдер.Контрагент, | ПриходныйКассовыйОрдер.ДоговорКонтрагента, | ПриходныйКассовыйОрдер.СуммаДокумента |ИЗ | Документ.ПриходныйКассовыйОрдер КАК ПриходныйКассовыйОрдер |ГДЕ | ПриходныйКассовыйОрдер.Дата >= &НачалоПериода"); Запрос.УстановитьПараметр("НачалоПериода", НачалоГода(ТекущаяДата())); ТЗ = Запрос.Выполнить().Выгрузить(); // Начало алгоритма КлючевыеКолонки = "Контрагент,ДоговорКонтрагента"; КолонкаСчетчик = "_Строк"; ТЗПовторы = ТЗ.Скопировать(, КлючевыеКолонки); ТЗПовторы.Колонки.Добавить(КолонкаСчетчик); ТЗПовторы.ЗаполнитьЗначения(1, КолонкаСчетчик); ТЗПовторы.Свернуть(КлючевыеКолонки, КолонкаСчетчик); БезПовторов = ТЗПовторы.НайтиСтроки(Новый Структура(КолонкаСчетчик, 1)); СтркутураПоиска = Новый Структура(КлючевыеКолонки); Для Каждого Ключ Из БезПовторов Цикл ЗаполнитьЗначенияСвойств(СтркутураПоиска, Ключ); СтрокиКУдалению = ТЗ.НайтиСтроки(СтркутураПоиска); Для Каждого Строка Из СтрокиКУдалению Цикл ТЗ.Удалить(Строка); КонецЦикла; КонецЦикла; |
|||
48
mistеr
30.10.19
✎
17:15
|
Что-то с форматтером
|
|||
49
mistеr
30.10.19
✎
17:16
|
Да, забыл:
ТЗ.Индексы.Добавить(КлючевыеКолонки); |
|||
50
MetaDon
30.10.19
✎
17:22
|
(46) конечно + еще убыстряем - вводим СЗ с номерами строк дублей,естественно их из проверки исключаем
|
|||
51
pechkin
30.10.19
✎
17:24
|
(46) это ты сортировку пузырьком взял
|
|||
52
new_hope
30.10.19
✎
17:33
|
(47) Уххх.. работает мгновенно на примерно 10-ти тысячах строк. Правда не проверял, насколько правдиво работает. Но наглядный результат - вроде как все верно!
|
|||
53
new_hope
30.10.19
✎
17:50
|
(47) Супер! Благодарю! То что надо!
|
|||
54
Garykom
гуру
30.10.19
✎
18:20
|
(52) Удаление строк из ТЗ обычно медленней чем перенос только нужных строк в новую ТЗ.
Так что перепиши на другие алгоритмы и протести |
|||
55
Сияющий в темноте
30.10.19
✎
18:43
|
(54)зависит от количества строк и количества колонок.
|
|||
56
Garykom
гуру
30.10.19
✎
18:53
|
(55) В платформе 1С удаление строки в ТЗ вызывает создание новой ТЗ с переносом туда строк.
Это так к сведению. |
|||
57
mistеr
30.10.19
✎
19:41
|
(56) Интересно. Есть подтверждения этому?
|
|||
58
mistеr
30.10.19
✎
19:43
|
(54) Судя по описанию ТС, в его случае удаляемых строк будет немного. Если много, то согласен, лучше формировать новую ТЗ.
|
|||
59
Garykom
гуру
30.10.19
✎
19:45
|
(57) Несколько раз было уже тут на форуме
|
|||
60
mistеr
30.10.19
✎
19:52
|
(59) Не встречал. Это были пруфы или предположения?
|
|||
61
H A D G E H O G s
30.10.19
✎
21:47
|
(3) Как ни очевидно, что за такие решения надо бить по почкам.
|
|||
62
H A D G E H O G s
30.10.19
✎
21:47
|
(60) Это эротические фантазии.
|
|||
63
Garykom
гуру
30.10.19
✎
22:10
|
(62) Это подтверждение или опровержение?
Вроде бы провалами в памяти еще не страдаю, тестил кто то засекая время и пробуя удалять строки и копировать ТЗ. |
|||
64
Garykom
гуру
30.10.19
✎
22:13
|
(61) В случае файловой базы это (запросом именно подобная задача) быстрее и проще, в случае отдельного sql сервера надо знать что будет делать сервер 1С, может он не будет передавать ему всю тз а сам на своем движке запрос выполнит.
Я если честно хз но свой движок запросов у сервера 1С точно есть. |
|||
65
АнализДанных
30.10.19
✎
22:37
|
(47) (52) Ещё можно к таблице индексы добавить, тогда ещё быстрее поиск будет:
Для Каждого ИмяКолонки Из СтрРазделить(КлючевыеКолонки, ",") Цикл ТЗ.Индексы.Добавить(ИмяКолонки); КонецЦикла; |
|||
66
mistеr
31.10.19
✎
08:56
|
(65) См. (49)
|
|||
67
new_hope
31.10.19
✎
10:30
|
Спасибо всем. Свою задачу я решил. Спасибо "mister"
Но - очень интересно реализовать это чисто ЗАПРОСом. Буду благодарен, если кто-то предоставит готовый запрос по подобной таблице. (для самообразования) |
|||
68
catena
31.10.19
✎
10:39
|
(67) такое, чтоли?
ВЫБРАТЬ п.Контрагент,п.ДоговорКонтрагента Договор,п.Ссылка,п.ДокументОснование,п.ВидОперации поместить тз ИЗ Документ.ПлатежноеПоручениеИсходящее КАК п; Выбрать п.Контрагент,п.Договор,Количество(п.Ссылка) поместить тз2 из тз п сгруппировать по п.Контрагент,п.Договор имеющие Количество(п.Ссылка)>1; Выбрать п.Контрагент,п.Договор,п.Ссылка,п.ДокументОснование,п.ВидОперации из тз п внутреннее соединение тз2 пп по п.Контрагент=пп.Контрагент и п.Договор=пп.Договор |
|||
69
rphosts
31.10.19
✎
10:42
|
(0) 1.Свернуть
2.Запросом 3.Отсортировать и программно. проще всего №1, быстрее всего №2, середнячок №3. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |