检索第二个 XML 值
Retrieving 2nd XML value
代码将 运行 但它不会 return 从下面的 XML 片段中获取我需要的所有值。如果存在 > 1 个当前或以前的状态,我该如何进行迭代,如何调整为 return CurrentStatus_1 = 1 vs CurrentStatus_1 =31
<account_status_counters>
<account type="current" description="Pays Account as Agreed" status="1">31</account>
<account type="current" description="Pays/Paid 60-90 Days or Max 3 Payments Past Due" status="3">1</account>
<account type="current" description="Bad Debt" status="9">2</account>
<account type="former" description="Pays/Paid 30-60 Days or Max 2 Payments Past Due" status="2">3</account>
<account type="former" description="Pays/Paid 60-90 Days or Max 3 Payments Past Due" status="3">1</account>
<account type="former" description="Bad Debt" status="9">6</account>
</account_status_counters>
;with XMLNAMESPACES ('http://cp.com/rules/client' as ns1)
select
id,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:admin/ns1:product_reference)[1]', 'varchar(15)') as Ref_Number,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status ="1"]/@description)[1]', 'varchar(50)') as CurrentDescription_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status ="1"])[1]', 'int') as CurrentStatus_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "]/@description)[1]', 'varchar(50)') as CurrentDescription_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "])[1]', 'int') as CurrentStatus_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "]/@description)[1]', 'varchar(50)') as CurrentDescription_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "])[1]', 'int') as CurrentStatus_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status ="1"]/@description)[1]', 'varchar(50)') as FormerDescription_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status ="1"])[1]', 'int') as FormerStatus_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "]/@description)[1]', 'varchar(50)') as FormerDescription_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "])[1]', 'int') as FormerStatus_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "]/@description)[1]', 'varchar(50)') as FormerDescription_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "])[1]', 'int') as FormerStatus_3
from Database.dbo.CreditData CS
带有简短描述的预期输出
当前结果及简短描述
由于未提供 DDL 和样本数据群,我胡乱猜测。
我不确定 Status(1-3) 列的来源是什么...似乎所需的输出屏幕截图有一些差异。
查看下面的解决方案。它明显不那么冗长。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, CreditScoreXML NVARCHAR(MAX));
INSERT INTO @tbl (CreditScoreXML) VALUES
(N'<ncf_report xmlns="http://cp.com/rules/client">
<admin>
<product_reference>1234567890</product_reference>
</admin>
<account_status_counters>
<account type="current" description="Pays Account as Agreed" status="1">31</account>
<account type="current"
description="Pays/Paid 60-90 Days or Max 3 Payments Past Due"
status="3">1</account>
<account type="current" description="Bad Debt" status="9">2</account>
<account type="former"
description="Pays/Paid 30-60 Days or Max 2 Payments Past Due"
status="2">3</account>
<account type="former"
description="Pays/Paid 60-90 Days or Max 3 Payments Past Due"
status="3">1</account>
<account type="former" description="Bad Debt" status="9">6</account>
</account_status_counters>
</ncf_report>')
-- DDL and sample data population, end
;WITH XMLNAMESPACES (DEFAULT 'http://cp.com/rules/client') ,rs AS
(
SELECT id, TRY_CAST(CreditScoreXML AS XML) AS xmldata
FROM @tbl
)
SELECT ID
, rs.xmldata.value('(/ncf_report/admin/product_reference/text())[1]','VARCHAR(15)') AS Ref_Number
, c.value('(account[@type="current" and @status ="1"]/@description)[1]','VARCHAR(50)') AS CDescription_1
, c.value('(account[@type="current" and @status ="1"]/@status)[1]','INT') AS CStatus_1
, c.value('(account[@type="current" and @status ="3"]/@description)[1]','VARCHAR(50)') AS CDescription_2
, c.value('(account[@type="current" and @status ="3"]/@status)[1]','INT') AS CStatus_2
, c.value('(account[@type="current" and @status ="9"]/@description)[1]','VARCHAR(50)') AS CDescription_3
, c.value('(account[@type="current" and @status ="9"]/@status)[1]','INT') AS CStatus_3
, c.value('(account[@type="former" and @status ="2"]/@description)[1]','VARCHAR(50)') AS FDescription_1
, c.value('(account[@type="former" and @status ="2"]/@status)[1]','INT') AS FStatus_1
, c.value('(account[@type="former" and @status ="3"]/@description)[1]','VARCHAR(50)') AS FDescription_2
, c.value('(account[@type="former" and @status ="3"]/@status)[1]','INT') AS FStatus_2
, c.value('(account[@type="former" and @status ="9"]/@description)[1]','VARCHAR(50)') AS FDescription_3
, c.value('(account[@type="former" and @status ="9"]/@status)[1]','INT') AS FStatus_3
FROM rs CROSS APPLY rs.xmldata.nodes('/ncf_report/account_status_counters') AS t(c);
Output
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
| ID | Ref_Number | CDescription_1 | CStatus_1 | CDescription_2 | CStatus_2 | CDescription_3 | CStatus_3 | FDescription_1 | FStatus_1 | FDescription_2 | FStatus_2 | FDescription_3 | FStatus_3 |
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
| 1 | 1234567890 | Pays Account as Agreed | 1 | Pays/Paid 60-90 Days or Max 3 Payments Past Due | 3 | Bad Debt | 9 | Pays/Paid 30-60 Days or Max 2 Payments Past Due | 2 | Pays/Paid 60-90 Days or Max 3 Payments Past Due | 3 | Bad Debt | 9 |
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
代码将 运行 但它不会 return 从下面的 XML 片段中获取我需要的所有值。如果存在 > 1 个当前或以前的状态,我该如何进行迭代,如何调整为 return CurrentStatus_1 = 1 vs CurrentStatus_1 =31
<account_status_counters>
<account type="current" description="Pays Account as Agreed" status="1">31</account>
<account type="current" description="Pays/Paid 60-90 Days or Max 3 Payments Past Due" status="3">1</account>
<account type="current" description="Bad Debt" status="9">2</account>
<account type="former" description="Pays/Paid 30-60 Days or Max 2 Payments Past Due" status="2">3</account>
<account type="former" description="Pays/Paid 60-90 Days or Max 3 Payments Past Due" status="3">1</account>
<account type="former" description="Bad Debt" status="9">6</account>
</account_status_counters>
;with XMLNAMESPACES ('http://cp.com/rules/client' as ns1)
select
id,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:admin/ns1:product_reference)[1]', 'varchar(15)') as Ref_Number,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status ="1"]/@description)[1]', 'varchar(50)') as CurrentDescription_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status ="1"])[1]', 'int') as CurrentStatus_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "]/@description)[1]', 'varchar(50)') as CurrentDescription_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "])[1]', 'int') as CurrentStatus_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "]/@description)[1]', 'varchar(50)') as CurrentDescription_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="current" and @status =" "])[1]', 'int') as CurrentStatus_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status ="1"]/@description)[1]', 'varchar(50)') as FormerDescription_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status ="1"])[1]', 'int') as FormerStatus_1,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "]/@description)[1]', 'varchar(50)') as FormerDescription_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "])[1]', 'int') as FormerStatus_2,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "]/@description)[1]', 'varchar(50)') as FormerDescription_3,
cast(CS.CreditScoreXML as xml).value('(ns1:ncf_report/ns1:report/ns1:summary/ns1:account_status_counters/ns1:account[@type="former" and @status =" "])[1]', 'int') as FormerStatus_3
from Database.dbo.CreditData CS
带有简短描述的预期输出
当前结果及简短描述
由于未提供 DDL 和样本数据群,我胡乱猜测。
我不确定 Status(1-3) 列的来源是什么...似乎所需的输出屏幕截图有一些差异。
查看下面的解决方案。它明显不那么冗长。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, CreditScoreXML NVARCHAR(MAX));
INSERT INTO @tbl (CreditScoreXML) VALUES
(N'<ncf_report xmlns="http://cp.com/rules/client">
<admin>
<product_reference>1234567890</product_reference>
</admin>
<account_status_counters>
<account type="current" description="Pays Account as Agreed" status="1">31</account>
<account type="current"
description="Pays/Paid 60-90 Days or Max 3 Payments Past Due"
status="3">1</account>
<account type="current" description="Bad Debt" status="9">2</account>
<account type="former"
description="Pays/Paid 30-60 Days or Max 2 Payments Past Due"
status="2">3</account>
<account type="former"
description="Pays/Paid 60-90 Days or Max 3 Payments Past Due"
status="3">1</account>
<account type="former" description="Bad Debt" status="9">6</account>
</account_status_counters>
</ncf_report>')
-- DDL and sample data population, end
;WITH XMLNAMESPACES (DEFAULT 'http://cp.com/rules/client') ,rs AS
(
SELECT id, TRY_CAST(CreditScoreXML AS XML) AS xmldata
FROM @tbl
)
SELECT ID
, rs.xmldata.value('(/ncf_report/admin/product_reference/text())[1]','VARCHAR(15)') AS Ref_Number
, c.value('(account[@type="current" and @status ="1"]/@description)[1]','VARCHAR(50)') AS CDescription_1
, c.value('(account[@type="current" and @status ="1"]/@status)[1]','INT') AS CStatus_1
, c.value('(account[@type="current" and @status ="3"]/@description)[1]','VARCHAR(50)') AS CDescription_2
, c.value('(account[@type="current" and @status ="3"]/@status)[1]','INT') AS CStatus_2
, c.value('(account[@type="current" and @status ="9"]/@description)[1]','VARCHAR(50)') AS CDescription_3
, c.value('(account[@type="current" and @status ="9"]/@status)[1]','INT') AS CStatus_3
, c.value('(account[@type="former" and @status ="2"]/@description)[1]','VARCHAR(50)') AS FDescription_1
, c.value('(account[@type="former" and @status ="2"]/@status)[1]','INT') AS FStatus_1
, c.value('(account[@type="former" and @status ="3"]/@description)[1]','VARCHAR(50)') AS FDescription_2
, c.value('(account[@type="former" and @status ="3"]/@status)[1]','INT') AS FStatus_2
, c.value('(account[@type="former" and @status ="9"]/@description)[1]','VARCHAR(50)') AS FDescription_3
, c.value('(account[@type="former" and @status ="9"]/@status)[1]','INT') AS FStatus_3
FROM rs CROSS APPLY rs.xmldata.nodes('/ncf_report/account_status_counters') AS t(c);
Output
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
| ID | Ref_Number | CDescription_1 | CStatus_1 | CDescription_2 | CStatus_2 | CDescription_3 | CStatus_3 | FDescription_1 | FStatus_1 | FDescription_2 | FStatus_2 | FDescription_3 | FStatus_3 |
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
| 1 | 1234567890 | Pays Account as Agreed | 1 | Pays/Paid 60-90 Days or Max 3 Payments Past Due | 3 | Bad Debt | 9 | Pays/Paid 30-60 Days or Max 2 Payments Past Due | 2 | Pays/Paid 60-90 Days or Max 3 Payments Past Due | 3 | Bad Debt | 9 |
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+