【问题标题】:Retrieving 2nd XML value检索第二个 XML 值
【发布时间】:2020-09-14 23:06:23
【问题描述】:

代码将运行,但它没有从下面的 XML 片段返回我需要的所有值。如果存在> 1个当前或以前的状态以及在何处存在,我如何进行迭代,我如何调整以返回 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 

带有缩写描述的预期输出

带有简短描述的当前结果

【问题讨论】:

  • 在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:stackoverflow.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑,你的代码尝试实现它。 (3) 基于上述#1 中的样本数据的期望输出。 (4) 你的 SQL Server 版本 (SELECT @@version;)

标签: xml tsql xquery sql-server-2016 xml-namespaces


【解决方案1】:

由于未提供 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);

输出

+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+
| 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 |
+----+------------+------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+-------------------------------------------------+-----------+-------------------------------------------------+-----------+----------------+-----------+

【讨论】:

  • 伟大的解决方案 Yitzhak!
  • @Ricky,很高兴听到建议的解决方案对您有用。请在 LinkedIn 上与我联系。
猜你喜欢
  • 1970-01-01
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
相关资源
最近更新 更多