我必须在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;
答案 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。编辑查询以准确匹配您需要的内容。