簡體   English   中英

SQL Server 2008 R2 - 遞歸SQL - 這可能嗎?

[英]SQL Server 2008 R2 - Recursive SQL - Is this possible?

我有下表:

| Article-Material1 | Article-Material2 |
|-------------------|-------------------|
| article001        | article002        |
| article001        | article003        |
| article001        | material001       |
| material001       |                   |
| article002        | article004        |
| article002        | material002       |
| material002       |                   |
| article003        | material003       |
| material003       |                   |
| article004        | material004       |
| material004       |                   |
| article005        | article010        |
| article005        | article011        |
| article005        | material001       |
| article010        | material005       |
| material005       |                   |
| article011        | article012        |
| article011        | material004       |
| article011        | material006       |
| material006       |                   |
| article012        | material002       |
| article012        | material007       |
| material007       |                   |

我想實現這樣的輸出:

article001
    |- article002
        |- article004
            |- material004
        |- material002
    |- article003
        |- material003
    |- material001
article005
    |- article010
        |- material005
    |- article011
        |- article012
            |- material002
            |- material007
        |- material004
        |- material006
    |- material001

我不知道這是否可以用SQL。 如果不可能,我還能做些什么來朝着正確的方向前進?

出於演示目的,您可以根據我以前的帖子使用以下代碼。
SQL挑戰/解謎:如何使用SQL查詢創建ASCII藝術層次結構樹?

with        h (id,pid)
            as
            (
                select      [Article-Material2] as id
                           ,[Article-Material1] as pid

                from        mytable

                where       [Article-Material2] is not null

                union all

                select      distinct
                            [Article-Material1]     as id
                           ,null                    as pid

                from        mytable

                where       [Article-Material1] not in (select [Article-Material2] from mytable where [Article-Material2] is not null)
            )       

           ,last_sibling (id)
            as
            (
                select      max (id)
                from        h
                group by    pid
            )

           ,tree (id,branch,path)
            as
            (
                select      h.id
                           ,cast ('' as varchar(max))
                           ,cast (h.id as varchar(max))

                from        h

                where       h.pid is null

                union all

                select      h.id
                           ,t.branch + case when (select 1 from last_sibling ls where ls.id = t.id) = 1 then ' ' else '|' end + '    '
                           ,t.path + '_' + h.id

                from                    tree            t

                            join        h

                            on          h.pid =
                                        t.id
            )

           ,vertical_space (n)
            as
            (
                select      1

                union all

                select      vs.n + 1
                from        vertical_space  vs
                where       vs.n < 2
            )

select      t.branch + case vs.n when 1 then '|____' + ' ' + t.id else '|' end

from                    tree            t

            cross join  vertical_space  vs

order by    t.path
           ,vs.n desc

option      (maxrecursion 0)
;

|
|____ article001
|    |
|    |____ article002
|    |    |
|    |    |____ article004
|    |    |    |
|    |    |    |____ material004
|    |    |
|    |    |____ material002
|    |
|    |____ article003
|    |    |
|    |    |____ material003
|    |
|    |____ material001
|
|____ article005
     |
     |____ article010
     |    |
     |    |____ material005
     |
     |____ article011
     |    |
     |    |____ article012
     |    |    |
     |    |    |____ material002
     |    |    |
     |    |    |____ material007
     |    |
     |    |____ material004
     |    |
     |    |____ material006
     |
     |____ material001
Declare @YourTable table ([Article-Material1] varchar(25),[Article-Material2] varchar(25))
Insert Into @YourTable values
('article001','article002'),
('article001','article003'),
('article001','material001'),
('material001',null),
('article002','article004'),
('article002','material002'),
('material002',null),
('article003','material003'),
('material003',null),
('article004','material004'),
('material004',null),
('article005','article010'),
('article005','article011'),
('article005','material001'),
('article010','material005'),
('material005',null),
('article011','article012'),
('article011','material004'),
('article011','material006'),
('material006',null),
('article012','material002'),
('article012','material007'),
('material007',null)


Declare @Top    varchar(25) = null       --<<  Sets top of Hier Try 'article002' 
Declare @Nest   varchar(25) = '|-----'  --<<  Optional: Added for readability

;with  cte0 as (
       Select ID=[Article-Material2]
             ,Pt=[Article-Material1]
       From   @YourTable
       Where  [Article-Material2] is not null
       Union All
       Select ID=[Article-Material1]
             ,Pt=null
       From   @YourTable
       Where  [Article-Material1] not in (Select [Article-Material2] from @YourTable where [Article-Material2] is not null) )               
,     cteP as (
      Select Distinct
             Seq  = cast(ID as varchar(500))
            ,ID
            ,Pt
            ,Lvl=1
      From   cte0 
      Where  IsNull(@Top,'X') = case when @Top is null then isnull(Pt,'X') else ID end
      Union  All
      Select Seq  = cast(p.Seq+'.'+r.ID+r.Pt as varchar(500))
            ,r.ID
            ,r.Pt
            ,p.Lvl+1
      From   cte0 r
      Join   cteP p on r.Pt = p.ID and r.Pt=p.ID)
     ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP )
     ,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select Distinct
       A.R1  
      ,B.R2
      ,A.ID
      ,A.Pt
      ,A.Lvl
      ,Title = Replicate(@Nest,A.Lvl-1) + A.ID
 From cteR1 A
 Join cteR2 B on A.Seq=B.Seq where R2>=R1
 Order By A.R1

返回

在此輸入圖像描述

現在,只是為了好玩,將@Top設置為'article002' ,你會得到:

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM