我有一个表,其中包含已更改为其他键的键。这些都是这样的:
origkey newkey
1 2
2 3
4 5
6 7
7 8
8 9
9 10
我想要完成的是一个获取orig的查询,并找到每个新的最大新密钥。在上面的示例中,结果如下所示:
origkey maxkey
1 3
4 5
6 10
如果我知道密钥可以更改的最大次数,我只需添加一定量的自联接并从那里获取。不幸的是,我不知道它过去可能改变了多少次。有没有办法保持自我加入,直到找到一个空?以下查询会将更改后的密钥返回到新列中,但我认为我在这里走错路,因为这样会得到1 - > 3改变,但不是6 - > 10改变。
select a.origkey
,a.newkey
,b.newkey newkey1
,c.newkey newkey2
from changedkeys a
Left Outer Join changedkeys b on a.newkey=b.origkey
Left Outer Join changedkeys c on b.newkey=c.origkey
答案 0 :(得分:1)
有一种方法。它被称为递归CTE:
with cte as (
select origkey, newkey, 1 as lev
from table1
union all
select cte.origkey, t1.newkey, lev + 1
from cte join
table1 t1
on cte.newkey = t1.origkey
)
select origkey, newkey as newestkey
from (select cte.*, row_number() over (partition by origkey order by lev desc) as seqnum
from cte
) t
where seqnum = 1;
请注意,这假定键定义中没有循环,如问题中的示例所示。如果这是可能的,可以修改递归CTE来处理这个问题。
编辑:
如果数据中有潜在的周期,请尝试以下方法:
with cte as (
select origkey, newkey, 1 as lev, ',' + cast(newkey as varchar(8000)) + ',' as keys
from table1
union all
select cte.origkey, t1.newkey, cte.lev + 1, keys + cast(t1.newkey as varchar(8000)) + ','
from cte join
table1 t1
on cte.newkey = t1.origkey
where ',' + t1.keys + ',' not like '%,' + cast(t1.newkey as varchar(8000)) + '%,'
)
select origkey, newkey as newestkey
from (select cte.*, row_number() over (partition by origkey order by lev desc) as seqnum
from cte
) t
where seqnum = 1;