如何仅从 SQL Server 2019 (v15) 中的 XML 解析最新条目(基于索引属性)?
How to parse latest entry only (based on index attribute) from an XML in SQL Server 2019 (v15)?
我正在处理具有以下结构的 XML 文件。我想要 select d5p1:id="W45A" 或 d5p1:id="W450" 条目的最新条目(这是 d5p1:index="0" 的位置),同时忽略任何旧条目。
我想要的输出看起来像这样。请注意,理想情况下我也将 W45025 包含为 null,尽管它根本没有包含在最新条目中:
Id
Term
W45A01
20211221
W45A02
4013072
W45A08
4
W45001
20211130
W45022
4043072
W45023
993344
W45024
0
W45025
NULL
<UcSwedishIndividualReport xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Content>
<status xmlns:d3p1="http://www.uc.se/schemas/ucOrderReply/" xmlns="http://www.uc.se/schemas/ucOrderReply/" d3p1:result="ok" />
<ucReport xmlns="http://www.uc.se/schemas/ucOrderReply/">
<xmlReply>
<reports xmlns:d5p1="http://www.uc.se/schemas/ucOrderReply/" d5p1:lang="eng">
<d5p1:report d5p1:id="6002124815" d5p1:name="'FirstName LastName" d5p1:styp="K39" d5p1:index="0">
<d5p1:group d5p1:id="W45A" d5p1:index="0" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45A01">20211221</d5p1:term>
<d5p1:term d5p1:id="W45A02">4013072</d5p1:term>
<d5p1:term d5p1:id="W45A08">4</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="0" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20211130</d5p1:term>
<d5p1:term d5p1:id="W45022">4043072</d5p1:term>
<d5p1:term d5p1:id="W45023">993344</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="1" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20210930</d5p1:term>
<d5p1:term d5p1:id="W45022">4240629</d5p1:term>
<d5p1:term d5p1:id="W45023">1185833</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="2" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20210731</d5p1:term>
<d5p1:term d5p1:id="W45022">4254142</d5p1:term>
<d5p1:term d5p1:id="W45023">1194268</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
<d5p1:term d5p1:id="W45025">3029874</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W495" d5p1:index="0" d5p1:key="" d5p1:name="Income info">
<d5p1:term d5p1:id="W49501">2021</d5p1:term>
<d5p1:term d5p1:id="W49517">411000</d5p1:term>
<d5p1:term d5p1:id="W49518">53400</d5p1:term>
<d5p1:term d5p1:id="W49522">410900</d5p1:term>
<d5p1:term d5p1:id="W49541">75200</d5p1:term>
<d5p1:term d5p1:id="W49591">75200</d5p1:term>
<d5p1:term d5p1:id="W49592">464300</d5p1:term>
</d5p1:group>
</d5p1:report>
</reports>
</xmlReply>
</ucReport>
</Content>
</UcSwedishIndividualReport>
我当前的代码只抓取所有值,不管它们的索引或 ID。问题是我不能用这种方法区分旧条目和最新条目。我之前曾尝试通过按读取顺序排列行然后 selecting 具有最低行等级的变量来区分值,但似乎代码并不总是加载table 从 id 0 开始,这打破了我的逻辑。
drop table #UC
;WITH XMLNAMESPACES('http://www.uc.se/schemas/ucOrderReply/' AS ns,'http://www.uc.se/schemas/ucOrderReply/' AS d5p1)
SELECT ok.*
,X.g.value('(@d5p1:id)','varchar(20)') AS id
,X.g.value('(text())[1]','varchar(20)') AS term
into #UC
FROM #1 as ok
CROSS APPLY ok.[Message].nodes('UcSwedishIndividualReport/Content/ns:ucReport/ns:xmlReply/ns:reports/ns:report/ns:group/ns:term') X(g)
我想您可以使用 XPath 来过滤特定的 <d5p1:group>
节点及其子节点。简化的 XPath 将是:
//d5p1:group[@d5p1:id="W45A" or @d5p1:id="W450"][@d5p1:index="0"]/d5p1:term
和简化查询:
SELECT term.value('@d5p1:id', 'varchar(100)') AS id, term.value('.', 'varchar(100)') AS term
FROM ... AS t(doc)
CROSS APPLY doc.nodes('//d5p1:group[@d5p1:id="W45A" or @d5p1:id="W450"][@d5p1:index="0"]/d5p1:term') x(term)
您可以通过它们的位置引用特定节点,即 node.[1]
或通过它们的属性值,如以下代码所示:
declare @xml xml = '...'
;WITH XMLNAMESPACES('http://www.uc.se/schemas/ucOrderReply/' AS ns,'http://www.uc.se/schemas/ucOrderReply/' AS d5p1)
SELECT
X.g.value('(@d5p1:id)','varchar(20)') AS id
,X.g.value('(text())[1]','varchar(20)') AS term
FROM @xml.nodes('UcSwedishIndividualReport/Content/ns:ucReport/ns:xmlReply/ns:reports/ns:report/ns:group[@d5p1:index="0" and (@d5p1:id="W45A" or @d5p1:id="W450")]') G(n)
CROSS APPLY G.n.nodes('ns:term') X(g)
如果您想在结果集中包含 id:W45025,它应该在 xml 中显示为空节点。另一种方法是将上述查询的结果加入 table 以及您想要的完整 ID 列表。
我正在处理具有以下结构的 XML 文件。我想要 select d5p1:id="W45A" 或 d5p1:id="W450" 条目的最新条目(这是 d5p1:index="0" 的位置),同时忽略任何旧条目。
我想要的输出看起来像这样。请注意,理想情况下我也将 W45025 包含为 null,尽管它根本没有包含在最新条目中:
Id | Term |
---|---|
W45A01 | 20211221 |
W45A02 | 4013072 |
W45A08 | 4 |
W45001 | 20211130 |
W45022 | 4043072 |
W45023 | 993344 |
W45024 | 0 |
W45025 | NULL |
<UcSwedishIndividualReport xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Content>
<status xmlns:d3p1="http://www.uc.se/schemas/ucOrderReply/" xmlns="http://www.uc.se/schemas/ucOrderReply/" d3p1:result="ok" />
<ucReport xmlns="http://www.uc.se/schemas/ucOrderReply/">
<xmlReply>
<reports xmlns:d5p1="http://www.uc.se/schemas/ucOrderReply/" d5p1:lang="eng">
<d5p1:report d5p1:id="6002124815" d5p1:name="'FirstName LastName" d5p1:styp="K39" d5p1:index="0">
<d5p1:group d5p1:id="W45A" d5p1:index="0" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45A01">20211221</d5p1:term>
<d5p1:term d5p1:id="W45A02">4013072</d5p1:term>
<d5p1:term d5p1:id="W45A08">4</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="0" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20211130</d5p1:term>
<d5p1:term d5p1:id="W45022">4043072</d5p1:term>
<d5p1:term d5p1:id="W45023">993344</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="1" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20210930</d5p1:term>
<d5p1:term d5p1:id="W45022">4240629</d5p1:term>
<d5p1:term d5p1:id="W45023">1185833</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W450" d5p1:index="2" d5p1:key="" d5p1:name="Credit commitments">
<d5p1:term d5p1:id="W45001">20210731</d5p1:term>
<d5p1:term d5p1:id="W45022">4254142</d5p1:term>
<d5p1:term d5p1:id="W45023">1194268</d5p1:term>
<d5p1:term d5p1:id="W45024">0</d5p1:term>
<d5p1:term d5p1:id="W45025">3029874</d5p1:term>
</d5p1:group>
<d5p1:group d5p1:id="W495" d5p1:index="0" d5p1:key="" d5p1:name="Income info">
<d5p1:term d5p1:id="W49501">2021</d5p1:term>
<d5p1:term d5p1:id="W49517">411000</d5p1:term>
<d5p1:term d5p1:id="W49518">53400</d5p1:term>
<d5p1:term d5p1:id="W49522">410900</d5p1:term>
<d5p1:term d5p1:id="W49541">75200</d5p1:term>
<d5p1:term d5p1:id="W49591">75200</d5p1:term>
<d5p1:term d5p1:id="W49592">464300</d5p1:term>
</d5p1:group>
</d5p1:report>
</reports>
</xmlReply>
</ucReport>
</Content>
</UcSwedishIndividualReport>
我当前的代码只抓取所有值,不管它们的索引或 ID。问题是我不能用这种方法区分旧条目和最新条目。我之前曾尝试通过按读取顺序排列行然后 selecting 具有最低行等级的变量来区分值,但似乎代码并不总是加载table 从 id 0 开始,这打破了我的逻辑。
drop table #UC
;WITH XMLNAMESPACES('http://www.uc.se/schemas/ucOrderReply/' AS ns,'http://www.uc.se/schemas/ucOrderReply/' AS d5p1)
SELECT ok.*
,X.g.value('(@d5p1:id)','varchar(20)') AS id
,X.g.value('(text())[1]','varchar(20)') AS term
into #UC
FROM #1 as ok
CROSS APPLY ok.[Message].nodes('UcSwedishIndividualReport/Content/ns:ucReport/ns:xmlReply/ns:reports/ns:report/ns:group/ns:term') X(g)
我想您可以使用 XPath 来过滤特定的 <d5p1:group>
节点及其子节点。简化的 XPath 将是:
//d5p1:group[@d5p1:id="W45A" or @d5p1:id="W450"][@d5p1:index="0"]/d5p1:term
和简化查询:
SELECT term.value('@d5p1:id', 'varchar(100)') AS id, term.value('.', 'varchar(100)') AS term
FROM ... AS t(doc)
CROSS APPLY doc.nodes('//d5p1:group[@d5p1:id="W45A" or @d5p1:id="W450"][@d5p1:index="0"]/d5p1:term') x(term)
您可以通过它们的位置引用特定节点,即 node.[1]
或通过它们的属性值,如以下代码所示:
declare @xml xml = '...'
;WITH XMLNAMESPACES('http://www.uc.se/schemas/ucOrderReply/' AS ns,'http://www.uc.se/schemas/ucOrderReply/' AS d5p1)
SELECT
X.g.value('(@d5p1:id)','varchar(20)') AS id
,X.g.value('(text())[1]','varchar(20)') AS term
FROM @xml.nodes('UcSwedishIndividualReport/Content/ns:ucReport/ns:xmlReply/ns:reports/ns:report/ns:group[@d5p1:index="0" and (@d5p1:id="W45A" or @d5p1:id="W450")]') G(n)
CROSS APPLY G.n.nodes('ns:term') X(g)
如果您想在结果集中包含 id:W45025,它应该在 xml 中显示为空节点。另一种方法是将上述查询的结果加入 table 以及您想要的完整 ID 列表。