Рекурсивная итерация в Oracle - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть такая таблица:

 +----+-----+------+
 | id | ord | test |
 +----+-----+------+
 |  1 |   1 | A    |
 |  1 |   2 | B    |
 |  1 |   3 | C    |
 |  2 |   1 | B    |
 |  2 |   2 | C    |
 +----+-----+------+

(Вот код для создания данных)

drop table temp_test;
create table temp_test (id varchar(20), ord varchar(20), test varchar(20));
insert into temp_test (id,ord,test) values ('1','1','A');
insert into temp_test (id,ord,test) values ('1','2','B');
insert into temp_test (id,ord,test) values ('1','3','C');
insert into temp_test (id,ord,test) values ('2','1','B');
insert into temp_test (id,ord,test) values ('2','2','C');
commit;

Как я могу получить следующий результат?

+----+-----+-------+
| id | ord | test  |
+----+-----+-------+
|  1 |   1 | A     |
|  1 |   2 | A_B   |
|  1 |   3 | A_B_C |
|  2 |   1 | B     |
|  2 |   2 | B_C   |
+----+-----+-------+

Я пытался использовать LAG (), что-то вроде:

  select CONCAT(lag(TEST) over (partition by ID order by ord),TEST) AS TEST from temp_test;

, но он не работает рекурсивно.

Этот код работает:

SELECT 
R1.*,
(   SELECT  LISTAGG(test, ';') WITHIN GROUP (ORDER BY ord)
    FROM    temp_test R2
    WHERE   R1.ord >= R2.ord
    AND     R1.ID = R2.ID
    GROUP BY ID
) AS WTR_KEYWORD_1
FROM temp_test R1
ORDER BY id, ord;

но это не достаточно эффективно для большего набора данных.

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Некоторые говорят, что Иерархические запросы устарели, но обычно они работают намного лучше, чем рекурсивный CTE

SELECT id,
       ord,
       LTRIM(sys_connect_by_path(test,'_'),'_') as test
FROM temp_test r2 START WITH ord = 1 -- use MIN() to get this if it's not always 1
CONNECT BY PRIOR id = id AND ord = PRIOR ord + 1;

Демо

0 голосов
/ 19 ноября 2018

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

with cte(id,ord,test,concat_val) 
  as (select id,ord,test,test as concat_val
       from temp_test
       where ord=1
      union all
      select a.id,a.ord,a.test,b.concat_val||'_'||a.test
        from temp_test a
        join cte b
          on a.id=b.id
         and a.ord=b.ord+1 
      )
select * from cte order by id,ord

Демо здесь

https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=78baa20f7f364e653899caf63ce7ada2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...