2017-01-19 4 views
3

У меня есть следующая таблица:SQL Server 2008 R2 - Рекурсивный SQL - возможно ли это?

| 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. Если это невозможно, что еще я могу попытаться получить в правильном направлении?

+0

как бы что выход выглядеть в виде таблицы? или это одна строка, отформатированная таким образом? – Stephen

+1

Возможно, но ваш вывод не является таблицей. Вы собираетесь использовать SQL для печати? Вернуть XML? Включить пустые столбцы? Повторить значения столбцов? SQL Server не имеет понятия вложенных таблиц (большинство систем баз данных нет, есть редкие исключения). –

+0

@ Stephen Это одна из моих многочисленных проблем с этим. Я не знаю, как положить это в таблицу. Мне нужна одна строка со всеми вспомогательными элементами для каждой основной статьи (статьи, которые живут только в первом иерархии). И мне нужно знать, на каком уровне иерархии присутствуют подэлементы. Конечная цель - экспортировать данные в файл Excel. В файле excel мне нужен вывод, как показано выше. – Hellenbeck

ответ

1
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 

Возвращает

enter image description here

Теперь, просто для удовольствия, установите @top к «article002» и вы получите:

enter image description here

+0

Еще раз спасибо. Это очень помогло мне. – Hellenbeck

3

Для целей презентации вы можете использовать следующий код на основании предыдущего сообщения.
SQL Challenge/Puzzle: How to create an ASCII art hierarchy tree with an SQL query?

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 
Смежные вопросы