我有一个类似这样的XML文件
declare @X XML
Set @X ='<A>
<B>
<C>161</C>
<D>190</D>
<E>43 ,44 ,48 ,49</E>
</B>
<B>
<C>162</C>
<D>190</D>
<E>100</E>
</B>
</A>
'
我想把它解析成表格:
C D E
161 190 43
161 190 48
161 190 49
162 190 100
我尝试使用
select
x.r.value('(A)[1]', 'int') as C,
x.r.value('(D)[1]', 'int') as D,
x.r.value('(E)[1]', 'varchar(max)') as E
from
@X.nodes('/A/B') as x(r)
DECLARE @xml as xml, @str as varchar(100), @delimiter as varchar(10)
SET @str = '43,48,49'
SET @delimiter = ','
SET @xml = cast(('<X>'+replace(@str,@delimiter ,'</X><X>')+'</X>') as xml)
SELECT T.N.value('.', 'int') as value FROM @xml.nodes('X') as T(N)
用于将逗号分隔的列E分隔到表中。
但我无法在一个查询中将这两者结合起来,即将其解析为表
答案 0 :(得分:2)
下次你应该真的避免&#34;变色龙&#34;的问题。特别是当对初始问题的更改使正确答案无效时,这被认为是不礼貌的......
你做了什么:通过接受最有用的答案并开始一个新问题来关闭这个问题。
然而,这是一种有效的方法:
DECLARE @X XML =
N'<A>
<B>
<C>161</C>
<D>190</D>
<E>43 ,44 ,48 ,49</E>
</B>
<B>
<C>162</C>
<D>190</D>
<E>100</E>
</B>
</A>';
WITH ReturnYourListAsXml AS
(
SELECT CAST(N'<x>' + REPLACE(B.value(N'(E/text())[1]',N'nvarchar(max)'),',','</x><x>') + '</x>' AS XML) AS E_As_Xml
,B.value(N'(C/text())[1]',N'int') AS C
,B.value(N'(D/text())[1]',N'int') AS D
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS B_Nr
FROM @x.nodes(N'/A/B') AS AllNodes(B)
)
SELECT cte.B_Nr
,cte.C
,cte.D
,YourList.Member.value(N'text()[1]',N'int') AS E
FROM ReturnYourListAsXml AS cte
CROSS APPLY E_As_Xml.nodes(N'/x') AS YourList(Member);
答案 1 :(得分:1)
我修改了我的原始答案,使用您修改过的问题,其中您有多个从属[B]节点。我也冒昧地修改数据,以便结果显而易见(所有&#34; 1&#34; s在一起等)。我喜欢Shnugo的另一个答案,XML分裂字符串版本。我有一段时间没有看到它,但我觉得它更干净,所以我用它。
DECLARE @builder AS TABLE
(
[C] [INT]
, [D] [INT]
, [E] [XML]
);
DECLARE @X XML ='<A>
<B>
<C>161</C>
<D>191</D>
<E>41 ,51 ,61 ,71</E>
</B>
<B>
<C>162</C>
<D>192</D>
<E>102</E>
</B>
<B>
<C>163</C>
<D>193</D>
<E>43, 53, 63</E>
</B>
</A>';
WITH [row_builder]
AS (SELECT t.c.query(N'.') AS [b_row]
FROM @X.nodes(N'/A/B') AS [t]([c]))
, [shredder]
AS (SELECT [b_row].value(N'(./B/C/text())[1]', N'[INT]') AS [C]
, [b_row].value(N'(./B/D/text())[1]', N'[INT]') AS [D]
, [b_row].value(N'(./B/E/text())[1]', N'[NVARCHAR](MAX)') AS [E]
FROM [row_builder])
, [splitter]
AS (SELECT [C]
, [D]
, cast(( '<E>' + replace([E], N',', '</E><E>') + '</E>' ) AS XML) AS [E]
FROM [shredder])
SELECT [C]
, [D]
, [column].query(N'.').value(N'(/E/text())[1]', N'[INT]') AS [E]
FROM [splitter] AS [entry]
CROSS APPLY [E].[nodes]('/*') AS [table] ( [column] )
ORDER BY [C]
, [D]
, [E];