简体   繁体   English

T-SQL 员工层次递归查询

[英]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

Demo 演示

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM