|
Перенос колонок у дублирующихся строк | ☑ | ||
---|---|---|---|---|
0
Штурман
15.11.13
✎
14:37
|
Есть результат запроса, в виде таблицы:
Первое Второе Третье ------ ------- ------- Иванов А М Иванов А Н Иванов А О Иванов Б Петров А П Петров А Р Сидоров А Нужно из этой таблицы дублирующиеся строки с определенным критерием перенести в новую колонку, т.е. в результате из этой таблицы должна получиться следующая: Первое Второе Третье Четвертое Пятое ------ ------- ------- ------ --------- Иванов А М Н О Иванов Б Петров А П Р Сидоров А Как видим, если есть дубликаты в первой колонке и значения во второй колонке равны, то у дубликатов переносим значения третьей колонки в четвертую и пятую. Как бы это в запросе реализовать или в таблице значений? Подскажите, плиз :) |
|||
1
regniws
15.11.13
✎
14:46
|
кажется только программно, сортируешь первое, второе, бежишь циклом и если равны, то модифицируешь предыдущую и удаляешь текущую.
|
|||
2
Штурман
15.11.13
✎
14:55
|
(1) программно, это цикл по таблице значений?
|
|||
3
regniws
15.11.13
✎
14:57
|
(2) угу
|
|||
4
kosts
15.11.13
✎
14:58
|
(0) Можно сделать запросом, если значения М,Н,О заданы заранее
|
|||
5
Штурман
15.11.13
✎
15:00
|
(4) допустим они известны заранее, т.е. предопределенные, как примерно?
|
|||
6
Штурман
15.11.13
✎
15:03
|
(3) Так примерно пойдет:
тз = Новый ТаблицаЗначений; тз.Колонки.Добавить("Первое"); тз.Колонки.Добавить("Второе"); тз.Колонки.Добавить("Третье"); тз.Колонки.Добавить("Четвертое"); тз.Колонки.Добавить("Пятое"); стр = тз.Добавить(); стр.Первое = "Иванов"; стр.Второе = "А"; стр.Третье = "M"; стр = тз.Добавить(); стр.Первое = "Иванов"; стр.Второе = "А"; стр.Третье = "N"; стр = тз.Добавить(); стр.Первое = "Иванов"; стр.Второе = "А"; стр.Третье = "O"; стр = тз.Добавить(); стр.Первое = "Иванов"; стр.Второе = "B"; стр = тз.Добавить(); стр.Первое = "Петров"; стр.Второе = "А"; стр.Третье = "M"; СтаршийИндекс = тз.Количество()-1; Для сч=0 по СтаршийИндекс Цикл если тз[сч].Первое = тз[сч+1].Первое тогда сообщить(тз[сч+1].Первое) иначе конецесли; КонецЦикла; Только потом выдает ошибку: "Индекс находится за границами массива если тз[сч].Первое = тз[сч+1].Первое тогда" |
|||
7
kosts
15.11.13
✎
15:05
|
|
|||
8
kosts
15.11.13
✎
15:07
|
(7) Потом нужно сгруппировать. Да и ограничение нарисовалось, МНО должны быть числами, что бы могло суммироваться.
|
|||
9
regniws
15.11.13
✎
15:09
|
(6) СтаршийИндекс = тз.Количество()-2, очевидно ж
если тз[сч].Первое = тз[сч+1].Первое И тз[сч].Второе = тз[сч+1].Второе тогда (7) ну и прикинь что это сделает с (0), мндэ |
|||
10
kosts
15.11.13
✎
15:17
|
(6) Можно такой подход.
Создать таблицу с 5 колонками. Цикл по первой таблице Ищем строку по ключевым данным во второй таблице. Если не находим строку, то добавляем. В найденную(додавленную) строку пишем значение в нужную колонку (М или Н или О) Повторить цикл сначала Т.е. примерно 10 строк вполне можно уложиться. |
|||
11
regniws
15.11.13
✎
15:27
|
(10) оценка времени работы алгоритма о(н^2)
|
|||
12
kosts
15.11.13
✎
15:34
|
(11) Если есть уверенность, что таблица 1 упорядочена, то без поиска можно сделать.
|
|||
13
bolobol
15.11.13
✎
15:40
|
Задача сводится к тому. чтобы выбрать для каждого уникальные записи без повторов, затем в каждой следующей колонке разместить значения, меньшие, чем в предыдущей колонке.
|
|||
14
Штурман
15.11.13
✎
15:45
|
(12) (13) да, таблица предположительно упорядочена, т.е. самые первые значения дубликатов и будут первыми уникальными значениями, к которым потом добавляются колонки остальных дубликатов
|
|||
15
Штурман
15.11.13
✎
15:49
|
Получается что на основе этой таблицы значений создаем новую таблицу значений, которую сворачиваем, потом перебрасываем туда колонки,
а в запросе группируем и перекидываем в таблицу значений так? |
|||
16
bolobol
15.11.13
✎
15:53
|
Запросом сложно сделать транспонирование. Запрос это выборки, соединения и - группировки. Группируем и подсчитываем максимум различных значений в каждой группе, чтобы знать количество итоговых колонок.
Обходя группировки - заполняем новую ТЗ. Один цикл по результату запроса. |
|||
17
bolobol
15.11.13
✎
15:54
|
Млин... не "в каждой группе", а просто - максимум различных значений "из всех групп"
|
|||
18
Штурман
18.11.13
✎
12:29
|
Товарищи, написал вот так:
з = тз.Количество(); СтаршийИндекс = тз.Количество()-2; //пока з> 0 цикл Для сч = 0 по СтаршийИндекс цикл если тз[сч].Первое= тз[сч+1].Первое И тз[сч].Второе= тз[сч+1].Второе тогда тз[сч].Четвертое = тз[сч+1].Третье; тз.Удалить(сч+1); конецесли; конеццикла; При работе выводит ошибку "Индекс находится за границами массива" |
|||
19
Штурман
18.11.13
✎
13:04
|
^
|
|||
20
kosts
18.11.13
✎
13:14
|
(18) > "Индекс находится за границами массива"
Естественно, ты же удаляешь строки. |
|||
21
Штурман
18.11.13
✎
13:24
|
(20) а что сделать, чтобы такой ошибки не возникало?
|
|||
22
kosts
18.11.13
✎
13:31
|
(21) Не обращаться за границы таблицы
|
|||
23
Штурман
18.11.13
✎
13:47
|
(22) а как кодом это сделать?
|
|||
24
George Wheels
18.11.13
✎
14:03
|
(23)
сч = 0; Пока Истина Цикл Если сч = ТЗ.Количество() - 1 Тогда Прервать; КонецЕсли; если тз[сч].Первое= тз[сч+1].Первое И тз[сч].Второе= тз[сч+1].Второе тогда тз[сч].Четвертое = тз[сч+1].Третье; тз.Удалить(сч+1); Иначе сч = сч + 1 конецесли; КонецЦикла |
|||
25
Штурман
18.11.13
✎
15:08
|
(24) Но тогда так удаляются все строки. А как потом добавить к Пятой колонке значение второго дубликата, что-то уже запутался...
тз[сч].Пятое = тз[сч+...].Второе |
|||
26
George Wheels
18.11.13
✎
15:16
|
(25) Удаляется только то, что ты хотел, т.е. строки с индексом сч+1 (которые уже перенесены). Если совпадения в условии Если нет, то индекс увеличивается на 1.
Только алгоритм переноса нужно переписать. |
|||
27
Штурман
18.11.13
✎
16:03
|
(26) сделал вот так: добавил в таблицу значений еще одну колонку "Счетчик"
сч=0; Пока истина цикл Если сч=тз.Количество()-1 тогда прервать; конецесли; если тз[сч].Первое = тз[сч+1].Первое И тз[сч].Второе = тз[сч+1].Второе тогда тз[сч].Четвертое = тз[сч+1].Третье; тз[сч].Счетчик = сч; // тз.Удалить(сч+1); //иначе сч = сч + 1; конецесли; конеццикла; Индекс = тз.Количество()-1; для сч=0 по Индекс цикл если тз[сч].Счетчик = Неопределено тогда тз.Удалить(сч); конецесли; конеццикла; сч=0; Пока истина цикл Если сч=тз.Количество()-1 тогда прервать; конецесли; если тз[сч].Первое = тз[сч+1].Первое И тз[сч].Второе = тз[сч+1].Второе тогда тз[сч].Пятое = тз[сч+1].Четвертое; тз[сч].Счетчик = сч; // тз.Удалить(сч+1); //иначе сч = сч + 1; конецесли; конеццикла; Индекс = тз.Количество()-1; для сч=0 по Индекс цикл если тз[сч].Счетчик = 1 тогда тз.Удалить(сч); конецесли; конеццикла; Работает как-бы нормально, но что-то код великоват получился, можно ли проще решить задачу из (0) ? |
|||
28
George Wheels
18.11.13
✎
16:26
|
если тз[сч].Первое = тз[сч+1].Первое И тз[сч].Второе = тз[сч+1].Второе тогда
Если Не ЗначениеЗаполнено(тз[сч].Четвертое) Тогда тз[сч].Четвертое = тз[сч+1].Третье; ИначеЕсли Не ЗначениеЗаполнено(тз[сч].Пятое) Тогда тз[сч].Пятое = тз[сч+1].Третье; Иначе Сообщить("Сюда попасть не должен, или есть шестой элемент"); КонецЕсли; тз.Удалить(сч+1); Иначе сч = сч + 1; КонецЕсли; |
|||
29
Штурман
18.11.13
✎
16:55
|
(28) спасибо, попробую :)
|
|||
30
Prince-Sentido
19.11.13
✎
19:59
|
Доброго времени суток, Штурман! Не знаю, когда сможете прочесть... Заинтересовался поставленной Вами задачей, написал алгоритм.
ТекущаяСтрока = Табличка[0].Первое; й = 3; ТаблицаДляУдаления = Новый ТаблицаЗначений; ТаблицаДляУдаления.Колонки.Добавить("Первое"); ТаблицаДляУдаления.Колонки.Добавить("Индекс", ОписаниеТипаЧисло); Для Каждого строка из Табличка Цикл Если строка.Первое = ТекущаяСтрока и Табличка.Индекс(строка) <> 0 Тогда Если Табличка.Колонки.Найти("Поле"+й) = Неопределено Тогда Табличка.Колонки.Добавить("Поле"+й, ОписаниеТипаСтрока, "Поле"+й, 15); КонецЕсли; Табличка[Табличка.Индекс(строка)-ТаблицаДляУдаления.НайтиСтроки(Новый Структура("Первое", строка.Первое)).Количество()-1][Табличка.Колонки.Индекс(Табличка.Колонки.Найти("Поле"+й))] = строка.Второе; ТекущаяСтрока = строка.Первое; нс = ТаблицаДляУдаления.Добавить(); нс.Первое = строка.Первое; нс.Индекс = Табличка.Индекс(строка); й = й + 1; Иначе ТекущаяСтрока = строка.Первое; й = 3; КонецЕсли; КонецЦикла; Это основная функция преобразующая данные, согласно заданию(только лишь ключ состоит из одного поля!). Для удаления ненужных строк(ТаблицаДляУдаления) упорядочиваю строки по колонке Индекс в порядке убывания, а затем уже удаляю их. Это связано с тем, чтобы не менялся индекс у еще не удаленных строк. Преимущество в том, что заранее не нужно знать количество будущих колонок Функция работает в обработке. Если есть вопросы, буду рад пообщаться. |
|||
31
Штурман
20.11.13
✎
14:38
|
(30) Попробую ваш алгоритм :)
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |