Возвращает вложенный XML для повторяющихся столбцов

#sql #sql-server #xml #sql-server-2008

#sql #sql-сервер #xml #sql-server-2008

Вопрос:

У меня есть таблица, которая выглядит следующим образом, поместите соответствующий код (в частности, структуры XML и запросы)

 Class Subclass   Information  Details
Classx subclassx Info1        otherinfo1 
Classx subclassx Info2
Classx subclassy info3 
Classyy subclassyyy info3 
  

В качестве примера мне нужно вернуть строки, отфильтрованные с помощью Class=’classx’, возвращая:

 <Class Name="Classx">
  <Subclass subclassName ="subclassx">
    <Info>Info1</Info>
    <Info>Info2</Info>
  </Subclass>  
 <Subclass subclassName ="subclassy">
    <Info>Info3</Info>
  </Subclass>  
</Class>
  

(или)

 <Class Name="Classx">
  <Subclass>subclassx
    <Info>Info1</Info>
    <Info>Info2</Info>
  </Subclass>
 <Subclass>subclassy
   <Info>Info3</Info>
 </Subclass>
</Class>
  

Что-то, что вкладывает ‘Подкласс’ внутри элемента ‘Class’ и ‘Info’ внутри элемента ‘Subclass’.

Некоторые запросы пытались:

 DECLARE @classFilter nvarchar(15);
SELECT @classFilter = 'Classx' 

     SELECT @classFilter as '@Class',
              (SELECT  r1.subClass as 'SubClass',
               (SELECT  DISTINCT r1.Info as 'Info' 
                   FROM @results as r2 
                   WHERE r2.Class=  @classFilter and r1.Subclass = r2.Subclass
                    FOR XML PATH('Information'), TYPE
                    )
               FROM @results r1 
              GROUP BY r1.Class, r1.SubClass, r1.Info
              HAVING r1.Class= @classFilter
                FOR XML PATH('Subclasses'), TYPE)
           FOR XML PATH('Class'), TYPE;
  

выдает:

 <Class Class="Classx">
  <Subclasses>
    <SubClass>subclassx</SubClass>
    <Information>
      <Info>Info1</Info>
    </Information>  
  </Subclasses>
 <Subclasses>
    <SubClass>subclassx</SubClass>
    <Information>
      <Info>Info2</Info>
    </Details>  
  </Subclasses>
<Subclasses>
    <SubClass>subclassy</SubClass>
    <Information>
      <Info>Info3</Info>
    </Information>  
  </Subclasses>
</Class>
  

Самое близкое, что я могу придумать, это

  SELECT @classfilter as '@Name',    --or r1.Class
        (SELECT r1.Subclass as '@Subclass', 
            (SELECT DISTINCT r1.Information as 'Information' 
               FROM @results as r2 
               WHERE r2.Class =  @classFilter and r1.Subclass = r2.Subclass         
                )
           FROM @results r1           
          GROUP BY r1.Class, r1.Subclass, r1.Information
          HAVING r1.Class= @classFilter 
            FOR XML PATH('Subclasses'), TYPE)
       FOR XML PATH('Class'), TYPE;
  

Выдает:

  <Class Name="classx">
      <Subclasses subclass="subclassx">Info1</Subclasses>
      <Subclasses subclass="subclassx">Info2</Subclasses>
      <Subclasses subclass="subclassy">Info3</Subclasses>
    </Class>
  

Интересно, чего мне не хватает!

Ответ №1:

 declare @T table
(
  Class varchar(10),
  Subclass varchar(10),
  Information varchar(10),
  Details varchar(10)
)

insert into @T 
select 'Classx', 'subclassx', 'Info1', 'otherinfo1' union all 
select 'Classx', 'subclassx', 'Info2', '' union all
select 'Classx', 'subclassy', 'info3', ''  union all
select 'Classyy', 'subclassyy', 'info3', '' 

declare @class varchar(10)
set @class = 'Classx'

select 
  T.Class as '@Name',
  (select
     T2.Subclass as '@subclassName',
     (select
        T3.Information as 'Info'
      from @T as T3
      where T3.Subclass = T2.Subclass and
            T3.Class = T.Class
      for xml path(''), type)
   from @T as T2
   where T.Class = T2.Class
   group by T2.Subclass
   for xml path('Subclass'), type)
from @T as T
where T.Class = @class
group by T.Class
for xml path('Class')