首页 > 解决方案 > Postgres XML 解析 - 使用 XPath 计算多个同名节点的总和

问题描述

我有一个如下的 xml 片段:

<OpCodeLaborInfo JobStatus="F" UpSellFlag="N" JobNo="1" OpCode="02TTZ10K" OpCodeDesc="10K SERVICE">
      <TechInfo ActualHrsWorked="2.50" CustTechRate="27.00" TechHrs="0.00" TechName="JEFF SELLERS" TechNo="4816" />
      <TechInfo ActualHrsWorked="0.00" CustTechRate="27.00" TechHrs="0.70" TechName="JEFF SELLERS" TechNo="4816" />
      <BillTimeRateHrs BillRate="129.97" />
      <CCCStmts Correction="PERFORMED 10K SERVICE" Complaint="LUBE OIL FILTER CHANGE, TIRE ROTATION, PERFORM MULTI POINT" />
      <CCCStmts Correction="X" Complaint="INSPECTION, INSPECT FILTERS AND RECOMMEND, INSPECT BRAKES," />
                    <CCCStmts Complaint="BELTS AND HOSES" />
      <RoAmts DlrCost="18.90" PayType="Cust" AmtType="Job" TotalAmt="59.12" />
</OpCodeLaborInfo>
<OpCodeLaborInfo JobStatus="F" UpSellFlag="N" JobNo="2" OpCode="02TTZ10K" OpCodeDesc="10K SERVICE">
          <TechInfo ActualHrsWorked="2.50" CustTechRate="27.00" TechHrs="1.00" TechName="JEFF SELLERS" TechNo="4816" />
          <TechInfo ActualHrsWorked="0.00" CustTechRate="27.00" TechHrs="0.00" TechName="JEFF SELLERS" TechNo="4816" />
          <BillTimeRateHrs BillRate="129.97" />
          <CCCStmts Correction="PERFORMED 10K SERVICE" Complaint="LUBE OIL FILTER CHANGE, TIRE ROTATION, PERFORM MULTI POINT" />
          <CCCStmts Correction="X" Complaint="INSPECTION, INSPECT FILTERS AND RECOMMEND, INSPECT BRAKES," />
          <CCCStmts Complaint="BELTS AND HOSES" />
          <RoAmts DlrCost="18.90" PayType="Cust" AmtType="Job" TotalAmt="59.12" />
</OpCodeLaborInfo>

我需要为每个 OpCodeLaborInfo 计算 TechInfo/@TechHrs 的总和。我尝试了以下方法:

unnest(xpath('sum(//dns:RepairOrder/dns:RoRecord/dns:Rolabor/dns:OpCodeLaborInfo/dns:TechInfo/@TechHrs[1])'::text,
      data_detail.ro_data_xml, 
      ARRAY[ARRAY['dns'::text, 'http://www.starstandards.org/STAR'::text]]))::text::numeric AS lbrsoldhours

但这似乎返回了两个 OpCodeLaborInfo 节点内的技术时间总和。有人能告诉我如何调整 xpath 以获得所需的结果。

所以基本上我需要:

工作 技术小时
1 总和(0.00+0.70)
2 总和(1.00+0.00)

标签: postgresqlxpath

解决方案


我会用xmltable()

select d.job, sum(t.hours)
from data_detail d
  cross join xmltable (
                '/OpCodeLaborInfo/TechInfo'
                passing d.ro_data_xml
                columns hours numeric path '@TechHrs') as t
group by d.job;

在线示例


XPath 可能不正确,因为您显示的 XPath 与您的示例 XML 数据不匹配。您的示例 XML 也不包含名称空间,所以我不确定您为什么要将一个名称传递给xpath()

但是如果你需要一个,你可以使用这样的东西:

  cross join xmltable (
                xmlnamespaces ('http://www.starstandards.org/STAR' as dns),
                '/dns:OpCodeLaborInfo/dns:TechInfo'
                passing d.ro_data_xml
                columns hours numeric path '@TechHrs') as t

推荐阅读