[英]T-SQL employee hierarchy recursive query
I would like to use a T-SQL query (it can be recursive CTE or anything) where I could get the following output as highlighted我想使用 T-SQL 查询(它可以是递归 CTE 或任何东西),我可以获得以下 output 突出显示
SQL to create sample table as follows SQL 创建示例表如下
--drop table #hierarchy
CREATE TABLE #hierarchy
(
ID INTEGER NOT NULL PRIMARY KEY,
Value CHAR(10) NOT NULL,
);
INSERT INTO #hierarchy
VALUES (1, 'a1'), (2, 'b2'), (3, 'c3'), (4, 'd4'),
(5, 'e5'), (6, 'f6'), (7, 'g7'), (8, 'h8');
Any suggestions welcome, have tried recursive cte similar to factorial manipulation, however would appreciate inputs.欢迎提出任何建议,尝试了类似于阶乘操作的递归 cte,但希望输入。
Thanks in advance.提前致谢。
You seem to be looking for string concatenation:您似乎正在寻找字符串连接:
select
id,
value,
(
select string_agg(trim(value), '->') within group(order by id)
from #hierarchy h1
where h1.id <= h.id
) path
from #hierarchy h
Demo on DB Fiddle : DB Fiddle 上的演示:
id | value | path
-: | :--------- | :----------------------------- 1 | a1 | a1
2 | b2 | a1->b2
3 | c3 | a1->b2->c3
4 | d4 | a1->b2->c3->d4
5 | e5 | a1->b2->c3->d4->e5
6 | f6 | a1->b2->c3->d4->e5->f6
7 | g7 | a1->b2->c3->d4->e5->f6->g7
8 | h8 | a1->b2->c3->d4->e5->f6->g7->h8
In versions of SQL Server that do not support `string_agg(), you would go:在不支持 `string_agg() 的 SQL 服务器版本中,您将 go:
select
id,
value,
stuff(
(
select distinct '->' + trim(h1.value) val
from #hierarchy h1
where h1.id <= h.id
order by val
for xml path(''), type
).value('.', 'nvarchar(max)')
, 1, 2, ''
) path
from #hierarchy h
You seem to want a cumulative string aggregation:你似乎想要一个累积的字符串聚合:
select string_agg(value, '->') over (order by id)
from hierarchy
But SQL Server doesn't support this.但是 SQL 服务器不支持这个。 Instead, you can use
cross apply
:相反,您可以使用
cross apply
:
select h.*, h2.str
from hierarchy h cross apply
(select string_agg(trim(value), '->') within group (order by id) as str
from hierarchy h2
where h2.id <= h.id
) h2
Here is a db<>fiddle. 这是一个 db<>fiddle。
If your names are non-overlapping, it might be more convenient to do the string concatenation once and then fetch the portions you want.如果您的名称不重叠,则进行一次字符串连接然后获取您想要的部分可能会更方便。 For your example data, this works:
对于您的示例数据,这有效:
select h.*, s.str,
left(s.str, patindex('%' + trim(h.value) + '%', s.str) + len(trim(h.value)) - 1)
from hierarchy h cross join
(select string_agg(trim(value), '->') within group (order by id) as str
from hierarchy
) s;
(And this could be made to work with overlapping strings, but the logic is a bit more cumbersome.) (这可以用于重叠字符串,但逻辑有点麻烦。)
You can also use recursive CTEs:您还可以使用递归 CTE:
with cte as (
select h.id, trim(h.value) as value, convert(varchar(max), trim(h.value)) as str
from hierarchy h
where id = 1
union all
select h.id, trim(h.value) as value, cte.str + '->' + trim(h.value) as str
from cte join
hierarchy h
on h.id = cte.id + 1
)
select *
from cte;
This uses the fact that the ids are sequential and have no gaps.这使用了 id 是连续的并且没有间隙的事实。 If that is not guaranteed, you can use
row_number()
to generate such a number.如果不能保证,您可以使用
row_number()
生成这样的数字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.