SQL Server递归查询以显示父级路径

问题描述

我正在使用sql Server语句,并且有一个像这样的表:

| item | value | parentItem |
+------+-------+------------+
|  1   | 2test |     2      |
|  2   | 3test |     3      |
|  3   | 4test |     4      |
|  5   | 1test |     1      |
|  6   | 3test |     3      |
|  7   | 2test |     2      |

我想使用sql Server语句获得以下结果:

| item1 | value1                   |
+-------+--------------------------+
|  1    | /4test/3test/2test       |
|  2    | /4test/3test             |
|  3    | /4test                   |
|  5    | /4test/3test/2test/1test |
|  6    | /4test/3test             |
|  7    | /4test/3test/2test       |

我没有找出正确的sql来根据parentItem获取所有id的所有值。

我已经尝试过此sql

with all_path as 
(
    select item,value,parentItem 
    from table 

    union all 

    select a.item,a.value,a.parentItem 
    from table a,all_path b
    where a.item = b.parentItem
)
select 
    item as item1,stuff(select '/' + value 
          from all_path 
          order by item asc 
          for xml path ('')),1,'') as value1 
from 
    all_path

但是得到的结果是“ value1”列,例如

/4test/4test/4test/3test/3test/3test/3test/2test/2test/2test/2test

您能帮我吗?非常感谢。

解决方法

根据您提供的预期输出,使用递归部分来连接值

;with yourTable as (
     select item,value,parentItem 
     from (values 
     (1,'2test',2),(2,'3test',3),(3,'4test',4),(5,'1test',1),(6,(7,2)
    )x (item,parentItem)
),DoRecursivePart as (

    select 1 as Pos,item,convert(varchar(max),value) value,parentItem 
    from yourTable
    union all
    select drp.pos +1,drp.item,yt.value + '/' + drp.value),yt.parentItem
    from yourTable yt
    inner join DoRecursivePart drp on drp.parentItem = yt.item

)
select drp.item,'/' + drp.value 
from DoRecursivePart drp
inner join (select item,max(pos) mpos 
            from DoRecursivePart 
            group by item) [filter] on [filter].item = drp.item and [filter].mpos = drp.Pos
order by item

给予

item        value
----------- ------------------
1           /4test/3test/2test
2           /4test/3test
3           /4test
5           /4test/3test/2test/1test
6           /4test/3test
7           /4test/3test/2test
,

这是示例数据

version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.34
    restart: always
    ports:
    - "4466:4466"
    environment:
      PRISMA_CONFIG: |
        port: 4466
        # uncomment the next line and provide the env var PRISMA_MANAGEMENT_API_SECRET=my-secret to activate cluster security
        # managementApiSecret: my-secret
        databases:
          default:
            connector: mysql
            host: host.docker.internal
            database: test_db
            user: root
            password: root
            rawAccess: true
            port: '8889'
            migrations: false

这是查询

drop table if exists dbo.test_table;
go
create table dbo.test_table(
  item                  int not null,[value]               varchar(100) not null,parentItem            int not null);

insert dbo.test_table values
(1,'test1','test2','test3','test4','test5','test6',2);

这是结果

;with recur_cte(item,[value],parentItem,h_level) as (
    select item,1 
    from dbo.test_table tt
    union all
    select rc.item,tt.[value],tt.parentItem,rc.h_level+1 
    from dbo.test_table tt join recur_cte rc on tt.item=rc.parentItem)
select rc.item,stuff((select '/' + cast(parentItem as varchar)
             from recur_cte c2
             where rc.item = c2.item
             order by h_level desc FOR XML PATH('')),1,'') [value1]
from recur_cte rc
group by item;