这听起来可能很愚蠢(是SQL Server的新功能),但是我正在寻求帮助,指导我如何在SQL Server中编写FOR XML
查询以将表导出为非常特定的嵌套格式。我正在将信息导入到的程序需要这种方式,否则它将无法正常工作。
这是我正在使用的表的示例。
下面是我正在寻找的输出。我可以使用此查询生成第一行,但我希望将其嵌套并使其看起来像下面的示例。我不确定如何使XML包装器成为该字段的值。将要使用此功能的最终软件只能使用具有数字的ID,因此这就是为什么我必须以自己的方式对其进行格式化的原因。希望有人可以为此提供指导和指导。
SELECT *
FROM Tbl_Store
FOR XML Path('Store')
<STORE>
<box1>
<item1>
<size>10</size>
<weight>15</weight>
</item1>
<item2>
<size>20</size>
<weight>25</weight>
</item2>
<item3>
<size>30</size>
<weight>35</weight>
</item3>
<item4>
<size>40</size>
<weight>45</weight>
</item4>
<item5>
<size>50</size>
<weight>55</weight>
</item5>
</box1>
<box2>
<item1>
<size>10</size>
<weight>15</weight>
</item1>
<item2>
<size>20</size>
<weight>25</weight>
</item2>
<item3>
<size>30</size>
<weight>35</weight>
</item3>
<item4>
<size>40</size>
<weight>45</weight>
</item4>
<item5>
<size>50</size>
<weight>55</weight>
</item5>
</box2>
</Store>
编辑 最终版本。感谢Shnugo
`SELECT ROW_NUMBER() OVER(ORDER BY Box) AS [@ID]
,M.Box as [BoxName]
,(
SELECT m2.Item AS [@ID]
,m2.Size AS [size]
,m2.[Weight] AS [weight]
FROM @mockup m2
WHERE m2.Box = m.Box
ORDER BY m2.Item
FOR XML PATH('item'),TYPE
)
FROM @mockup m
GROUP BY m.Box
FOR XML PATH('box'),ROOT('Store')`
答案 0 :(得分:1)
首先:对于下一个问题:请不要将数据作为图片发布。最好键入[mcve],这没什么好玩的,您可以检查一下我的答案如何在表变量中提供消耗性数据。
第二:名称-编号是一个非常糟糕的主意。人们应该从不做类似
的操作<item1/>
<item2/>
而且-要回答您的问题-FOR XML
不支持,至少不是直接支持。
问题是:任何查询都具有动态元素(数据)和元元素(结构)。您不能动态别名列(换句话说:将数据值用作结果集中的列名称)。
如果您不能避免这样做(我真的建议您重新选择此选项),我们必须使用技巧。
EXEC()
您的数据作为模型表
DECLARE @mockup TABLE(Box VARCHAR(10),Item INT,Size INT,[Weight] INT);
INSERT INTO @mockup VALUES
('box1',1,10,15)
,('box1',2,20,25)
,('box1',3,30,35)
,('box1',4,40,45)
,('box1',5,50,55)
,('box2',1,10,15)
,('box2',2,20,25)
,('box2',3,30,35)
,('box2',4,40,45)
,('box2',5,50,55);
这有效,但是非常丑陋,我现在必须洗手:-)
SELECT CAST(
CONCAT('<Store>'
,(
SELECT CONCAT('<',Box,'>'
,(
SELECT CONCAT('<item',Item,'>'
,'<size>',m2.Size,'</size>'
,'<weight>',m2.[Weight],'</weight>'
,'</item',Item,'>')
FROM @mockup m2
WHERE m2.Box=m.Box
ORDER BY m2.Item
FOR XML PATH(''),TYPE).value('.','nvarchar(max)')
,'</',Box,'>')
FROM @mockup m
GROUP BY m.Box
FOR XML PATH(''),TYPE).value('.','nvarchar(max)')
,'</Store>')
AS XML);
结果
<Store>
<box1>
<item1>
<size>10</size>
<weight>15</weight>
</item1>
<item2>
<size>20</size>
<weight>25</weight>
</item2>
<item3>
<size>30</size>
<weight>35</weight>
</item3>
<item4>
<size>40</size>
<weight>45</weight>
</item4>
<item5>
<size>50</size>
<weight>55</weight>
</item5>
</box1>
<box2>
<item1>
<size>10</size>
<weight>15</weight>
</item1>
<item2>
<size>20</size>
<weight>25</weight>
</item2>
<item3>
<size>30</size>
<weight>35</weight>
</item3>
<item4>
<size>40</size>
<weight>45</weight>
</item4>
<item5>
<size>50</size>
<weight>55</weight>
</item5>
</box2>
</Store>
这就是您应该做的:
SELECT ROW_NUMBER() OVER(ORDER BY Box) AS [@index]
,(
SELECT m2.Item AS [@index]
,m2.Size AS [size]
,m2.[Weight] AS [weight]
FROM @mockup m2
WHERE m2.Box = m.Box
ORDER BY m2.Item
FOR XML PATH('item'),TYPE
)
FROM @mockup m
GROUP BY m.Box
FOR XML PATH('box'),ROOT('Store')
结果接近您所需的结果,但设计合理:
<Store>
<box index="1">
<item index="1">
<size>10</size>
<weight>15</weight>
</item>
<item index="2">
<size>20</size>
<weight>25</weight>
</item>
<item index="3">
<size>30</size>
<weight>35</weight>
</item>
<item index="4">
<size>40</size>
<weight>45</weight>
</item>
<item index="5">
<size>50</size>
<weight>55</weight>
</item>
</box>
<box index="2">
<item index="1">
<size>10</size>
<weight>15</weight>
</item>
<item index="2">
<size>20</size>
<weight>25</weight>
</item>
<item index="3">
<size>30</size>
<weight>35</weight>
</item>
<item index="4">
<size>40</size>
<weight>45</weight>
</item>
<item index="5">
<size>50</size>
<weight>55</weight>
</item>
</box>
</Store>