在XQUERY中进行排序和合并

时间:2016-04-14 11:16:28

标签: xml xquery

我很难根据我需要应用的一些合并规则对一组XML进行排序。我在XQuery 1.0中这样做,并且一直在玩distinct-values函数,但发现很难将我需要的所有记录联系起来。

我试图应用的逻辑是

  • 频率和付款人需要存在一种情况,而且贡献类型相同。
  • 一次出现的是具有最新日期的组合的实例
  • 如果详细信息出现在具有相同,最近日期,日期,付款人和频率的同一记录中,则需要将它们合并,以便为该特定日期的频率和付款人显示的金额是支付的总金额日期。
  • 如果列表中存在多个记录,则需要合并详细信息以获得具有最新日期的组合的实例。

任何帮助都会非常感激。

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

1 个答案:

答案 0 :(得分: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>

由于您的日期格式是按照字典排序顺序正确排序的,因此您也可以直接比较字符串:

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()作为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'))