Oracle中的递归迭代

时间:2018-11-19 16:35:41

标签: sql oracle

我有一张这样的桌子:

 +----+-----+------+
 | 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 :(得分:1)

您可以利用递归cte实现此目的

Row col1    col2    col3     
1   aa,a    bbb     ccc  

此处演示

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

答案 1 :(得分:1)

有人说Hierarchical queries已过时,但它们的性能通常远胜于递归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;

Demo