递归 CTE T- SQL 链中的最低值
Recursive CTE T- SQL lowest value in the chain
这是 table 设置。
create table ids
(
id int not null,
new_id int not null
)
GO
insert ids (id, new_id) values(290, 190)
insert ids (id, new_id) values(390, 190)
insert ids (id, new_id) values(490, 190)
insert ids (id, new_id) values(580, 280)
insert ids (id, new_id) values(680, 280)
insert ids (id, new_id) values(280, 150)
insert ids (id, new_id) values(780, 150)
insert ids (id, new_id) values(990, 620)
insert ids (id, new_id) values(150, 140)
GO
数据
id new_id
-----------
290 190
390 190
490 190
580 280
680 280
280 150
780 150
990 620
150 140
我被解析为新的id,新的id总是低于初始id。
我想要 ID 和它们的最低值 new_ids。
到目前为止我的尝试是这样的。
with cte_ids as
(
select
a.id,
a.new_id
from
ids a
left join
ids b on a.new_id = b.id
where
b.id is null
union all
select
c.id,
c.new_id
from
ids c
join
cte_ids d on d.id = c.new_id
)
select * from cte_ids
returns
的结果
id new_id
------------
290 190
390 190
490 190
990 620
150 140
280 150
780 150
580 280
680 280
结果不正确,因为 id 580 应该是 140,因为 580 变成了 280,然后 280 变成了 150,然后 150 变成了 140。
预期结果是
id new_id
------------
290 190
390 190
490 190
580 140
680 140
280 140
780 140
990 620
150 140
如何得到这个结果?
用CASE
计算lowest_new_id
:
with cte_ids as
(
select a.id, a.new_id, lowest_new_id = a.new_id
from ids a
left join ids b on a.new_id = b.id
where b.id is null
union all
select c.id, c.new_id,
lowest_new_id = CASE WHEN d.lowest_new_id < c.new_id
THEN d.lowest_new_id ELSE c.new_id
END
from ids c
join cte_ids d on d.id = c.new_id
)
select *
from cte_ids;
据我了解你的问题,你想遵循原始 table 中每个 id
的关系,并带来最新的 new_id
.
考虑:
with cte_ids as (
select id, new_id, 1 lvl from ids
union all
select c.id, i.new_id, c.lvl + 1
from cte_ids c
inner join ids i on i.id = c.new_id
)
select id, new_id
from cte_ids c
where c.lvl = (select max(c1.lvl) from cte_ids c1 where c1.id = c.id)
order by id
理由:
递归查询的锚select所有id
s
然后递归部分遵循关系,同时跟踪原始 id
,并在每次迭代时递增一个名为 lvl
的计数器
外部查询过滤器按 id
最高 lvl
id | new_id
--: | -----:
150 | 140
280 | 140
290 | 190
390 | 190
490 | 190
580 | 140
680 | 140
780 | 140
990 | 620
这是 table 设置。
create table ids
(
id int not null,
new_id int not null
)
GO
insert ids (id, new_id) values(290, 190)
insert ids (id, new_id) values(390, 190)
insert ids (id, new_id) values(490, 190)
insert ids (id, new_id) values(580, 280)
insert ids (id, new_id) values(680, 280)
insert ids (id, new_id) values(280, 150)
insert ids (id, new_id) values(780, 150)
insert ids (id, new_id) values(990, 620)
insert ids (id, new_id) values(150, 140)
GO
数据
id new_id
-----------
290 190
390 190
490 190
580 280
680 280
280 150
780 150
990 620
150 140
我被解析为新的id,新的id总是低于初始id。
我想要 ID 和它们的最低值 new_ids。
到目前为止我的尝试是这样的。
with cte_ids as
(
select
a.id,
a.new_id
from
ids a
left join
ids b on a.new_id = b.id
where
b.id is null
union all
select
c.id,
c.new_id
from
ids c
join
cte_ids d on d.id = c.new_id
)
select * from cte_ids
returns
的结果id new_id
------------
290 190
390 190
490 190
990 620
150 140
280 150
780 150
580 280
680 280
结果不正确,因为 id 580 应该是 140,因为 580 变成了 280,然后 280 变成了 150,然后 150 变成了 140。
预期结果是
id new_id
------------
290 190
390 190
490 190
580 140
680 140
280 140
780 140
990 620
150 140
如何得到这个结果?
用CASE
计算lowest_new_id
:
with cte_ids as
(
select a.id, a.new_id, lowest_new_id = a.new_id
from ids a
left join ids b on a.new_id = b.id
where b.id is null
union all
select c.id, c.new_id,
lowest_new_id = CASE WHEN d.lowest_new_id < c.new_id
THEN d.lowest_new_id ELSE c.new_id
END
from ids c
join cte_ids d on d.id = c.new_id
)
select *
from cte_ids;
据我了解你的问题,你想遵循原始 table 中每个 id
的关系,并带来最新的 new_id
.
考虑:
with cte_ids as (
select id, new_id, 1 lvl from ids
union all
select c.id, i.new_id, c.lvl + 1
from cte_ids c
inner join ids i on i.id = c.new_id
)
select id, new_id
from cte_ids c
where c.lvl = (select max(c1.lvl) from cte_ids c1 where c1.id = c.id)
order by id
理由:
递归查询的锚select所有
id
s然后递归部分遵循关系,同时跟踪原始
id
,并在每次迭代时递增一个名为lvl
的计数器外部查询过滤器按
最高id
lvl
id | new_id --: | -----: 150 | 140 280 | 140 290 | 190 390 | 190 490 | 190 580 | 140 680 | 140 780 | 140 990 | 620