递归父ID

时间:2017-01-23 17:12:21

标签: sql sql-server

我有一个包含部门数据的表,它具有以下结构,

+----------+--------+----------+
| deptName | deptID | deptHier |  
+----------+--------+----------+
| a        |      1 |        1 |  
| b        |      2 |      1.2 |  
| c        |      3 |    1.2.3 |  
+----------+--------+----------+

deptHier列包含所有父ID的ID以及它自己的ID。

我想获得所有父母的姓名,包括孩子的名字。像这样的东西,

+----------+--------+----------+--------------+
| deptName | deptID | deptHier | deptHierName |
+----------+--------+----------+--------------+
| a        |      1 |        1 | a            |
| b        |      2 |      1.2 | a.b          |
| c        |      3 |    1.2.3 | a.b.c        |
+----------+--------+----------+--------------+

我已尝试在deptHier中使用带有1个id的方法并尝试将其拆分,但我甚至都没有关闭。 如果有人能提供帮助,那就太棒了。提前谢谢。

2 个答案:

答案 0 :(得分:2)

没有解析功能的选项

Declare @YourTable table (deptName varchar(50),deptID int,deptHier varchar(50))
Insert Into @YourTable values
('a',1,'1'),
('b',2,'1.2'),
('c',3,'1.2.3')

Select A.*
 From  @YourTable A
 Cross Apply (
         Select deptHierName  = Stuff((Select '.' +deptName 
         From (
                 Select Top 100 Percent *
                  From (
                         Select RetSeq = Row_Number() over (Order By (Select null))
                               ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                         From  (Select x = Cast('<x>'+ replace((Select A.deptHier as [*] For XML Path('')),'.','</x><x>')+'</x>' as xml).query('.')) as X 
                         Cross Apply x.nodes('x') AS B(i)
                       ) X
                 Join @YourTable D on (X.RetVal=D.deptID)
                 Order By RetVal
              ) S
          For XML Path ('')),1,1,'')
 ) B

<强>返回

enter image description here

答案 1 :(得分:1)

rextester:http://rextester.com/KKLDZ64185

create table tmp (deptName varchar(32),deptID int,deptHier varchar(32))
  insert into tmp (deptName,deptID,deptHier) values
      ('a',1,'1')
    , ('b',2,'1.2')
    , ('c',3,'1.2.3');
go

字符串拆分功能:

create function dbo.DelimitedSplitN4K (
    @pString nvarchar(4000)
  , @pDelimiter nchar(1)
  )
returns table with schemabinding as
return
  with e1(n) as (
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all select 1
  )
  , e2(n) as (select 1 from e1 a, e1 b)
  , e4(n) as (select 1 from e2 a, e2 b)
  , cteTally(n) as (select top (isnull(datalength(@pString)/2,0))
      row_number() over (order by (select null)) from e4)
  , cteStart(n1) as (select 1 union all 
      select t.n+1 from cteTally t where substring(@pString,t.n,1) = @pDelimiter)
  , cteLen(n1,l1) as(select s.n1
  ,   isnull(nullif(charindex(@pDelimiter,@pString,s.n1),0)-s.n1,4000)
    from cteStart s
  )
 select ItemNumber = row_number() over(order by l.n1)
      , Item       = substring(@pString, l.n1, l.l1)
   from cteLen l;
go

查询:

select t.*,x.*
  from tmp t
    cross apply (
      select DeptHierName = stuff((
        select '.'+p.deptName 
          from tmp P 
            inner join dbo.DelimitedSplitN4K(t.deptHier,'.') s 
              on p.deptId = s.Item
          order by ItemNumber
          for xml path (''), type).value('.','varchar(max)'),1,1,'')) x

返回以下内容:

+----------+--------+----------+--------------+
| deptName | deptID | deptHier | deptHierName |
+----------+--------+----------+--------------+
| a        |      1 |        1 | a            |
| b        |      2 |      1.2 | a.b          |
| c        |      3 |    1.2.3 | a.b.c        |
+----------+--------+----------+--------------+

拆分字符串参考: