【问题标题】:SQL replacement for Recursive CTE递归 CTE 的 SQL 替换
【发布时间】:2016-04-05 11:48:32
【问题描述】:

我有一个表测试,其中包含

TEST
----
tablename|columnvalue|rankofcolumn
A|C1|1
A|C2|2
A|C3|3
A|C4|4
B|CX1|1
B|CX2|2
C|CY1|1
C|CY2|2
C|CY3|3

我想生成路径以及其他列如下

RESULT
----
tablename|columnvalue|rankofcolumn|path
A|C1|1|C1
A|C2|2|C1->C2
A|C3|3|C1->C2->C3
A|C4|4|C1->C2->C3->C4
B|CX1|1|CX1
B|CX2|2|CX1->CX2
C|CY1|1|CY1
C|CY2|2|CY1->CY2
C|CY3|3|CY1->CY2->CY3

根据question,我可以使用递归 CTE 来实现这一点

WITH r ( tablename, columnvalue, rankofcolumn, PATH ) AS
         (SELECT    tablename,
                    columnvalue,
                    rankofcolumn,
                    columnvalue
          FROM      test
          WHERE     rankofcolumn = 1
          UNION ALL
          SELECT    xx.tablename,
                    xx.columnvalue,
                    xx.rankofcolumn,
                    r.PATH || '->' || xx.columnvalue
          FROM      r
                    JOIN test xx
                        ON     xx.tablename = r.tablename
                           AND xx.rankofcolumn = r.rankofcolumn + 1)
SELECT    *
FROM      r;

但我正在使用目前缺少此选项的 WX2 数据库。是否有 SQL 替代方案?

【问题讨论】:

  • WX2 不会促进 CTE,或者您正在为此输出寻求其他解决方案
  • 在上一个问题中您说允许中间表;还可以吗?
  • @AlexPoole 是的。我们可以有中间表或视图。
  • @mohan111 是的,我正在为这个输出寻求另一种解决方案

标签: sql common-table-expression recursive-cte wx2


【解决方案1】:

您可以对逐渐填充的表格执行蛮力方法。假设您的 test 表如下所示:

create table test (tablename varchar2(9), columnvalue varchar2(11), rankofcolumn number);

那么result 表可以通过以下方式创建:

create table result (tablename varchar2(9), columnvalue varchar2(11), rankofcolumn number,
  path varchar2(50));

然后为最低排名创建结果条目:

insert into result (tablename, columnvalue, rankofcolumn, path)
select t.tablename, t.columnvalue, t.rankofcolumn, t.columnvalue
from test t
where t.rankofcolumn = 1;

3 rows inserted.

并在现有最高等级的基础上重复添加行,从test 表中获取以下值(如果tablename 有任何值):

insert into result (tablename, columnvalue, rankofcolumn, path)
select t.tablename, t.columnvalue, t.rankofcolumn,
  concat(concat(r.path, '->'), t.columnvalue)
from test t
join result r
on r.tablename = t.tablename
and r.rankofcolumn = t.rankofcolumn - 1
where t.rankofcolumn = 2;

3 rows inserted.

insert into result (tablename, columnvalue, rankofcolumn, path)
select t.tablename, t.columnvalue, t.rankofcolumn,
  concat(concat(r.path, '->'), t.columnvalue)
from test t
join result r
on r.tablename = t.tablename
and r.rankofcolumn = t.rankofcolumn - 1
where t.rankofcolumn = 3;

2 rows inserted.

insert into result (tablename, columnvalue, rankofcolumn, path)
select t.tablename, t.columnvalue, t.rankofcolumn,
  concat(concat(r.path, '->'), t.columnvalue)
from test t
join result r
on r.tablename = t.tablename
and r.rankofcolumn = t.rankofcolumn - 1
where t.rankofcolumn = 4;

1 row inserted.

并继续争取尽可能多的列数(即任何表的最高 rankofcolumn)。您可以在 WX2 中以程序方式执行此操作,迭代直到插入零行;但你让它听起来很有限。

在所有这些迭代之后,表格现在包含:

select * from result
order by tablename, rankofcolumn;

TABLENAME COLUMNVALUE RANKOFCOLUMN PATH                                             
--------- ----------- ------------ --------------------------------------------------
A         C1                     1 C1                                                
A         C2                     2 C1->C2                                            
A         C3                     3 C1->C2->C3                                        
A         C4                     4 C1->C2->C3->C4                                    
B         CX1                    1 CX1                                               
B         CX2                    2 CX1->CX2                                          
C         CY1                    1 CY1                                               
C         CY2                    2 CY1->CY2                                          
C         CY3                    3 CY1->CY2->CY3                                     

在 Oracle 中测试,但试图避免任何特定于 Oracle 的内容;当然可能需要针对 WX2 进行调整。

【讨论】:

  • 感谢@Alex。但是,如果我们可以在 JOIN 中完成所有这些步骤?我可以有一个配置表来说明级别并执行 CROSS JOIN 来实现这一点?
  • 并非没有递归。您不能在选择中创建/插入;这就是 CTE 有用的部分原因。我想你可以有一个(非递归的)CTE 来执行一堆联合,每个联合中逐渐增加更多的自连接,但这更加混乱。
  • 感谢您的真诚努力。谢谢老哥
猜你喜欢
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多