来自一个数据透视表的SQL FOR XML多级 - 分组数据

时间:2014-04-30 22:09:37

标签: sql sql-server xml for-xml

这比这里发布的问题更进一步:link。提出的解决方案运行良好,但现在我有一个更难的场景,同样的解决方案没有应用,因为SQL不允许创建第三个嵌套SELECT。 现在的情况是dub标记可以在每个location内重复,每个dub可能包含多个data标记。 一个例子:

<locations>
  <location>
    <loc name="Country 1" id="1" />
    <dubs>
      <dub name="City 1">
        <data year="1950" value="2.43" />
        <data year="1955" value="2.55" />
      </dub>
      <dub name="City 2">
        <data year="1950" value="5.67" />
        <data year="1955" value="4.42" />
      </dub>
    </dubs>
  </location>
  <location>
    <loc name="Country 2" id="2" />
    <dubs>
      <dub bane="City ABC">
        <data year="1950" value="4.54" />
        <data year="1955" value="42.15" />
      </dub>
    </dubs>
  </location>
</locations>

我尝试过第三次嵌套SELECT,但不允许这样做: SQL Fiddle - Not Working

select T.Country as 'loc/@name',
       T.ID as 'loc/@id',
       (
         select [City] as 'dub/@name',
         (
           select 1950 as 'dub/data/@year',
                  T.[1950] as 'dub/data/@value',
                  null,
                  1955 as 'dub/data/@year',
                  T.[1955] as 'dub/data/@value'
           for xml path(''), type
          ) as dub
       ) as dubs
from YourTable as T
for xml path('location'), root('locations'), type

我修改了原始问题的解决方案并生成了以下查询,该查询几乎可以正常工作: SQL Fiddle - Almost Working

    select T.Country as 'loc/@name',
       T.ID as 'loc/@id',
       (
         select [City] as 'dub/@name',
                 1950 as 'dub/data/@year',
                  T.[1950] as 'dub/data/@value',
                  null,
                  1955 as 'dub/data/@year',
                  T.[1955] as 'dub/data/@value'
           for xml path(''), type
       ) as dubs
from YourTable as T
for xml path('location'), root('locations'), type

但是,您会发现data标记未在其dub标记内进行分组 - 正在使用空白dub标记重新创建name标记{1}}属性内容。 有什么帮助吗?

1 个答案:

答案 0 :(得分:0)

谢谢,加斯珀,你们非常乐于助人! (加斯珀是我想象中的朋友)

我找到了解决方案,如下: SQL Fiddle

select Country as 'loc/@name',
       ID as 'loc/@id',
       (
         select [City] as 'dub/@name',
           (
               select 1950 as 'data/@year',
                  [1950] as 'data/@value',
                  null,
                  1955 as 'data/@year',
                  [1955] as 'data/@value'
               from YourTable as D
               where Country = C.Country
               and City = T.City
               for xml path(''), type
             ) as 'dub/datavalues'
         from
         (
           select distinct City
           from YourTable
           where Country = C.Country
         ) as T
         for xml path(''), type
       ) as 'loc/dubs'
from
(
  select distinct Country, ID
  from YourTable
) as C
for xml path(''), root('locations'), type

:)