2016-04-14 56 views
0

我很难根据需要应用的某些合并规则对一组XML进行排序。我在XQuery 1.0中这样做,并且一直在玩独特值函数,但却很难将我需要的所有记录联系起来。在XQUERY中排序和合并

我尝试应用的逻辑是

  • 需要有存在的频率和付款人和地方贡献类型是一样的每个组合中的一种发生。
  • 出现一次时是具有最近的日期是组合的实例
  • 如果细节出现在使用相同的,最近的日期,日期,付款人和频率则需要对它们进行合并,使得同一记录显示该频率和该特定日期的付款人的金额是该日期支付的总金额。
  • 如果列表中存在超过记录,则需要合并详细信息以得出具有最近日期的组合的实例。

任何帮助将非常感激。

 <transaction_history> 
     <contribution_transaction contribution_type="Type A" currency="GBP"> 
      <date>2015-12-31</date> 
      <payer>Employer</payer> 
      <amount>5042.38</amount> 
      <frequency>Quarterly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type A" currency="GBP"> 
      <date>2015-12-31</date> 
      <payer>Employer</payer> 
      <amount>4676.94</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type B" currency="GBP"> 
      <date>2015-09-08</date> 
      <payer>Employer</payer> 
      <amount>4317.52</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type A" currency="GBP"> 
      <date>2015-12-31</date> 
      <payer>Employer</payer> 
      <amount>9393.11</amount> 
      <frequency>Quarterly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type A" currency="GBP"> 
      <date>2015-10-02</date> 
      <payer>Employee</payer> 
      <amount>3944.49</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type B" currency="GBP"> 
      <date>2015-12-31</date> 
      <payer>Employee</payer> 
      <amount>3675.85</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type B" currency="GBP"> 
      <date>2015-10-02</date> 
      <payer>Employee</payer> 
      <amount>3385.69</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
     <contribution_transaction contribution_type="Type A" currency="GBP"> 
      <date>2015-12-31</date> 
      <payer>Employee</payer> 
      <amount>7369.64</amount> 
      <frequency>Monthly</frequency> 
     </contribution_transaction> 
    </transaction_history> 

<contribution_transaction contribution_type="Type A" currency="GBP"> 
     <date>2015-12-31</date> 
     <payer>Employer</payer> 
     <amount>5042.38</amount> 
     <frequency>Quarterly</frequency> 
    </contribution_transaction> 
<contribution_transaction contribution_type="Type A" currency="GBP"> 
     <date>2015-12-31</date> 
     <payer>Employer</payer> 
     <amount>5042.38</amount> 
     <frequency>Quarterly</frequency> 
    </contribution_transaction> 

的例子会导致:

<contribution_transaction contribution_type="Type A" currency="GBP"> 
     <date>2015-12-31</date> 
     <payer>Employer</payer> 
     <amount>10084.76</amount> 
     <frequency>Quarterly</frequency> 
    </contribution_transaction> 
+0

应该发生什么如果有多个'contribution_transaction'具有相同的'frequency','payer'和'date'? –

+0

嗨,Leo,那么金额将需要加总,然后导致只有一个contribution_transaction。实际上我需要考虑贡献类型属性,我已经意识到我忘了包含这些属性。 – user1905307

回答

0

您可以在其他以后做两个嵌套集团之一:

for $frequency in distinct-values(//frequency) 
let $contrib := //contribution_transaction[frequency = $frequency] 
for $payer in distinct-values($contrib/payer) 
let $res := $contrib[payer = $payer] 
let $min-date := min($res/date/xs:date(.)) 
return <result frequency="{$frequency}" payer="{$payer}">{ 
    (: do something clever with the relevant transactions here :) 
    $res[xs:date(date) = $min-date] 
}</result> 

由于您的日期格式与lexicog正确排序raphic排序顺序,也可以只直接比较字符串:

for $frequency in distinct-values(//frequency) 
let $contrib := //contribution_transaction[frequency = $frequency] 
for $payer in distinct-values($contrib/payer) 
let $res := $contrib[payer = $payer] 
let $min-date := min($res/date/string()) 
return <result frequency="{$frequency}" payer="{$payer}">{ 
    (: do something clever with the relevant transactions here :) 
    $res[date = $min-date] 
}</result> 

由于您的处理器似乎只支持node() S作为参数传递给fn:min(...),您可以使用此快速更换:

declare function local:min($seq) { 
    local:min((), $seq) 
}; 

declare function local:min($min, $seq) { 
    if(empty($seq)) then $min 
    else (
    let $first := $seq[1], $rest := $seq[position() > 1] 
    return (
     if($min < $first) then local:min($min, $rest) 
     else local:min($first, $rest) 
    ) 
) 
}; 

(: example usage :) 
local:min(('B', 'A', 'b')) 
+0

你认为我需要在将日期传递给min()函数之前去掉日期中的连字符,不要认为它会转换为double吗? – user1905307

+0

在我的查询中,我将它转换为'xs:date',这是XQuery原生支持的日期格式。比较两个字符串总是按照字典顺序进行;如果你想比较它们为'xs:double's,你必须明确地转换它们中的至少一个。 –

+0

感谢您的回应。在尝试此操作时,我似乎遇到错误:{err} XP0004 [{bea-err} XP0004b]:在表达式中发现类型不匹配。只有空序列满足类型检查规则。预期类型:节点*。 实际类型:{http://www.w3.org/2001/XMLSchema}date* – user1905307