SQL Server表中的XML列 - 将重复标记名称组合到一列中

时间:2017-02-20 13:53:59

标签: sql sql-server xml

我必须在SQL Server中查询XML数据列,并且需要一些帮助来了解如何查询XML中的一些单独的标记。

这是我用来测试查询的玩具数据集:

<SampleData>
    <ColumnGroup Usage="INEQUALITY">
        <Column Name="col1"/>
    </ColumnGroup>
    <ColumnGroup Usage="INCLUDE">
        <Column Name="col2"/>
        <Column Name="col3"/>
        <Column Name="col4"/>
        <Column Name="col5"/>
    </ColumnGroup>
</SampleData>

我想从查询中获得的结果如下:

 CT1          CN1    CT2         CN2
 -----------------------------------------------------
 INEQUALITY   col1   INCLUDE     col2, col3, col4, col5

我遇到的问题是能够查询XML以放置列&#39; CN2&#39;一起。我已经想出了一个查询来获得前3列而不是最后一列(CN2)。

这里是我目前的查询(#queryPlan是我创建的用于存储XML的临时表,query_plan是带有XML的列):

SELECT 
    query_plan.value('(/SampleData/ColumnGroup/@Usage)[1]', 'varchar(max)') as [CT1],
    query_plan.value('(/SampleData/ColumnGroup/Column/@Name)[1]', 'varchar(max)') as [CN1],
    query_plan.value('(/SampleData/ColumnGroup/@Usage)[2]', 'varchar(max)') as [CT2]
FROM 
    #queryPlan

但是我没想到这个查询的第四列。我遇到的问题是将子标签组合成一个单独的列。有关如何实现这一目标的任何建议?感谢。

编辑:这是我能够实现的答案。

SELECT  CT1 = t.query_plan.value('(SampleData/ColumnGroup/@Usage)[1]', 'NVARCHAR(MAX)'),
    CN1 = STUFF((SELECT CONCAT(',', i.X.value('@Name', 'NVARCHAR(MAX)'))
                FROM    t.query_plan.nodes('SampleData/ColumnGroup[1]/Column') AS i (X)
                FOR XML PATH('')), 1, 1, ''),
    CT2 = t.query_plan.value('(SampleData/ColumnGroup/@Usage)[2]', 'NVARCHAR(MAX)'),
    CN2 = STUFF((SELECT CONCAT(',', i.X.value('@Name', 'NVARCHAR(MAX)'))
                FROM    t.query_plan.nodes('SampleData/ColumnGroup[2]/Column') AS i (X)
                FOR XML PATH('')), 1, 1, '')
FROM    #queryPlan t;

3 个答案:

答案 0 :(得分:1)

我认为有一种方法可以在不先将不同元素分成行,添加逗号,然后使用FOR XML PATH()将行连接回单个列的情况下执行此操作:

DECLARE @T TABLE (X XML);
INSERT @T (X)
VALUES ('
<SampleData>
    <ColumnGroup Usage="INEQUALITY">
        <Column Name="col1"/>
    </ColumnGroup>
    <ColumnGroup Usage="INCLUDE">
        <Column Name="col2"/>
        <Column Name="col3"/>
        <Column Name="col4"/>
        <Column Name="col5"/>
    </ColumnGroup>
</SampleData>');

SELECT  CT1 = t.x.value('(SampleData/ColumnGroup/@Usage)[1]', 'NVARCHAR(MAX)'),
        CN1 = STUFF((SELECT CONCAT(',', i.X.value('@Name', 'NVARCHAR(MAX)'))
                    FROM    t.X.nodes('SampleData/ColumnGroup[1]/Column') AS i (X)
                    FOR XML PATH('')), 1, 1, ''),
        CT2 = t.x.value('(SampleData/ColumnGroup/@Usage)[2]', 'NVARCHAR(MAX)'),
        CN2 = STUFF((SELECT CONCAT(',', i.X.value('@Name', 'NVARCHAR(MAX)'))
                    FROM    t.X.nodes('SampleData/ColumnGroup[2]/Column') AS i (X)
                    FOR XML PATH('')), 1, 1, '')
FROM    @T t;

答案 1 :(得分:0)

你在找这样的东西吗?

DECLARE @xml XML=
N'<SampleData>
  <ColumnGroup Usage="INEQUALITY">
    <Column Name="col1" />
  </ColumnGroup>
  <ColumnGroup Usage="INCLUDE">
    <Column Name="col2" />
    <Column Name="col3" />
    <Column Name="col4" />
    <Column Name="col5" />
  </ColumnGroup>
</SampleData>';
select @xml

SELECT cg.value('(@Usage)[1]', 'varchar(max)') as ColumnGroupUsage
      ,c.value('(@Name)[1]','varchar(max)') AS ColumnName
FROM @xml.nodes(N'SampleData/ColumnGroup') AS A(cg)
OUTER APPLY cg.nodes(N'Column') AS B(c)

结果

INEQUALITY  col1
INCLUDE     col2
INCLUDE     col3
INCLUDE     col4
INCLUDE     col5

答案 2 :(得分:0)

如果您需要在一列中用逗号分隔,那么这就是您的代码:

DECLARE @xml XML=
N'<SampleData>
  <ColumnGroup Usage="INEQUALITY">
    <Column Name="col1" />
  </ColumnGroup>
  <ColumnGroup Usage="INCLUDE">
    <Column Name="col2" />
    <Column Name="col3" />
    <Column Name="col4" />
    <Column Name="col5" />
  </ColumnGroup>
</SampleData>';
select @xml

SELECT 
    cg.value('(@Usage)[1]', 'varchar(max)')                 as CT1
    ,(  select ', ' + c1.value('(@Name)[1]','varchar(max)') 
        from cg.nodes(N'Column') as C(c1) 
        for xml path(''), type
        ).value('substring(text()[1], 2)', 'varchar(max)')  as CN1
    ,c.value('(@Usage)[1]', 'varchar(max)')                 as CT2
    ,(  select ', ' + c2.value('(@Name)[1]','varchar(max)') 
        from c.nodes(N'Column') as D(c2) 
        for xml path(''), type
        ).value('substring(text()[1], 2)', 'varchar(max)')  as CN2
FROM 
    @xml.nodes(N'SampleData/ColumnGroup[1]') as A(cg)
    cross apply @xml.nodes(N'SampleData/ColumnGroup[2]') as B(c)

结果是: Query Result

P.S。编辑查询以准确匹配您需要的内容。