以一对多关系查询XML数据

时间:2018-10-10 03:46:26

标签: sql sql-server xml

我无法在SQL Server中提出查询以将以下XML数据转换成我想要的格式。标题和详细信息元素之间存在一对多的关系。我希望输出中每个细节元素都有一行。

示例代码

declare @xmldata xml;
set @xmldata =
'
<DATA>
    <HEADER>
        <HEADER_ID>1</HEADER_ID>
        <OPERATOR>BOB</OPERATOR>
        <TEST>RANDOM</TEST>
        <DATE>1/1/2018</DATE>
        <PARAMETER>XYZ</PARAMETER>
        <DETAILS>
            <DETAIL>
                <VALUE>5</VALUE>
                <RESULT>PASS</RESULT>
            </DETAIL>
            <DETAIL>
                <VALUE>10</VALUE>
                <RESULT>FAIL</RESULT>
            </DETAIL>
        </DETAILS>
    </HEADER>
    <HEADER>
        <HEADER_ID>2</HEADER_ID>
        <OPERATOR>Joe</OPERATOR>
        <TEST>RANDOM</TEST>
        <DATE>1/2/2018</DATE>
        <PARAMETER>XYZ</PARAMETER>
        <DETAILS>
            <DETAIL>
                <VALUE>1</VALUE>
                <RESULT>PASS</RESULT>
            </DETAIL>
            <DETAIL>
                <VALUE>23</VALUE>
                <RESULT>FAIL</RESULT>
            </DETAIL>
            <DETAIL>
                <VALUE>56</VALUE>
                <RESULT>FAIL</RESULT>
            </DETAIL>
        </DETAILS>
    </HEADER>
</DATA>'

select
x.y.value('HEADER_ID[1]','int') as [HEADER_ID],
x.y.value('OPERATOR[1]','char(10)') as [OPERATOR],
x.y.value('TEST[1]','char(10)') as [TEST],
x.y.value('DATE[1]','date') as [DATE],
x.y.query('./DETAILS/DETAIL/VALUE') as [VALUE],
x.y.query('./DETAILS/DETAIL/RESULT') as [RESULT]
from @xmlData.nodes('/DATA/HEADER') as x(y)

Current Result

Desired Result

2 个答案:

答案 0 :(得分:0)

使用cross apply访问所有其他节点。

select
    d.value('HEADER_ID[1]'  ,   'int')              as HEADER_ID    ,
    d.value('OPERATOR[1]'   ,   'char(10)')         as OPERATOR     ,
    d.value('TEST[1]'       ,   'char(10)')         as TEST         ,
    d.value('DATE[1]'       ,   'date')             as [DATE]       ,
    f.value('VALUE[1]'      ,   'int')              as [VALUE]      ,
    f.value('RESULT[1]'     ,   'nvarchar(100)')    as RESULT
from
(
    select
        @xmlData
)
    as a(b)
cross apply
    b.nodes('/DATA/HEADER')     as c(d)
cross apply
    d.nodes('./DETAILS/DETAIL') as e(f);

答案 1 :(得分:0)

使用CROSS APPLYDETAIL元素级别上切碎XML:

select
    x.y.value('HEADER_ID[1]','int') as [HEADER_ID],
    x.y.value('OPERATOR[1]','char(10)') as [OPERATOR],   
    x.y.value('TEST[1]','char(10)') as [TEST],   
    x.y.value('DATE[1]','date') as [DATE],
    t.c.value('VALUE[1]','int') as [VALUE],
    t.c.value('RESULT[1]','varchar(10)') as [RESULT]
from @xmlData.nodes('/DATA/HEADER') as x(y)
    cross apply x.y.nodes('DETAILS/DETAIL') as t(c)

演示:http://www.sqlfiddle.com/#!18/9eecb/35798