一个表中的SQL xml多级结构

时间:2013-10-09 13:02:02

标签: sql sql-server xml sqlxml

我在MS SQL Server数据库中有一个表,其结构如下:

 | goodId | pos     | description | docType        | isKey |
 +--------+---------+-------------+----------------+-------+
 | 1417   | NULL    | List 1050   | 1050.0000.0000 | 0     |
 | 1417   | 2.1.1.1 | hgfhgf9     | 1050.0002.0000 | 1     |
 | 1417   | 2.1.1.2 | hghgfh0     | 1050.0002.0000 | 1     |
 | 1417   | 2.1.1.3 | wwwwww      | 1050.0002.0000 | 1     |
 | 1417   | NULL    | List 1030   | 1030.0000.0000 | 0     |
 | 1417   | 1.3.7.6 | tdgfdgfd    | 1030.0001.0001 | 1     |
 | 1417   | 9.2.1.2 | gdfgfdfd    | 1030.0001.0009 | 1     |
 | 1417   | 9.2.1   | dddddddd    | 1030.0002.0009 | 1     |

在最后一列[docType]中,前4个字符表示列表编号,后4个字符表示部件编号。我需要获取isKey = 1的位置,但是列表的描述应该从只填充4个第一个字符的行中获取(这将是该列表的描述)

我希望使用SQL XML从此表中获取XML结构:

 <good Id="1417">
  <list num="1050" description="List 1050"> 
    <part num="2">
      <pos num = "2.1.1.1"/>
      <pos num= "2.1.1.2"/>
      <pos num= "2.1.1.3"/>
    </part>
  </list>
  <list num="1030" description="List 1030">
    <part num="1">
      <pos num = "1.3.7.6"/>
      <pos num = "9.2.1.2"/>
    </part>
    <part num="2">
      <pos num = "9.2.1"/>
    </part>
  </list>
</good>

我应该编写什么查询来获取此XML结构?

2 个答案:

答案 0 :(得分:1)

不记得是否可以不使用这样的重型嵌套:

;with cte as (
    select
        goodId, pos, description,
        left(docType, 4) as list_num,
        cast(substring(docType, 6, 4) as int) as part_num,
        left(docType, 9) as full_part_num
    from Table1
)
select
    t1.goodId as Id,
    (
        select
            t2.list_num as num,
            t2.description,
            (
                select
                    t3.part_num as num,
                    (
                        select
                            t4.pos as num
                        from cte as t4
                        where t4.full_part_num = t3.full_part_num
                        for xml raw('pos'), type
                    )
                from cte as t3
                where
                    t3.goodId = t1.goodId and t3.list_num = t2.list_num and
                    t3.pos is not null
                group by t3.part_num, t3.full_part_num
                for xml raw('part'), type
            )
        from cte as t2
        where t2.goodId = t1.goodId and t2.pos is null
        for xml raw('list'), type
    )
from cte as t1
group by t1.goodId
for xml raw('good');

<强> sql fiddle demo

答案 1 :(得分:1)

怪异的查询。

declare @MyTable table (goodId int, pos varchar(100), description varchar(100), docType varchar(100), isKey bit)

insert into @MyTable (goodId, pos, description, docType, isKey) values
(1417,  NULL,     'List 1050', '1050.0000.0000', 0),
(1417, '2.1.1.1', 'hgfhgf9',   '1050.0002.0000', 1),
(1417, '2.1.1.2', 'hghgfh0',   '1050.0002.0000', 1),
(1417, '2.1.1.3', 'wwwwww',    '1050.0002.0000', 1),
(1417,  NULL,     'List 1030', '1030.0000.0000', 0),
(1417, '1.3.7.6', 'tdgfdgfd',  '1030.0001.0001', 1),
(1417, '9.2.1.2', 'gdfgfdfd',  '1030.0001.0009', 1),
(1417, '9.2.1',   'dddddddd',  '1030.0002.0009', 1)

select g.goodId as '@Id'
    , (
        select l.num as '@num'
            , l.description as '@description'
            , (
                select cast(pa.num as int) as '@num'
                    , (
                        select po.pos as '@num'
                        from @MyTable po
                        where g.goodId = po.goodId and po.pos is not null and l.num = parsename(po.docType, 3) and pa.num = parsename(po.docType, 2)
                        for xml path('pos'), type
                    ) as [*]
                from (
                    select distinct parsename(pa.docType, 2) num
                    from @MyTable pa
                    where g.goodId = pa.goodId and pa.pos is not null and l.num = parsename(pa.docType, 3)
                ) pa
                for xml path('part'), type
            ) as [*]
        from (
            select distinct parsename(l.docType, 3) num, l.description
            from @MyTable l
            where g.goodId = l.goodId and l.pos is null
        ) l
        order by l.num
        for xml path('list'), type
    ) as [*]
from (
    select distinct goodId
    from @MyTable
) g
for xml path('good'), type