xquery有助于从不同的元素节点

时间:2016-05-28 13:35:06

标签: xquery

请帮助我了解如何使用xquery编写此类查询。 我有这个.xml:

<auctions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <products>
  <product id="1">
     <name>Name1</name>
  </product>
  <product id="2">
     <name>Name2</name>
  </product>
  <product id="3">
     <name>Name3</name>
  </product>
  <product id="4">
     <name>Name4</name>
  </product>
</products>
  <users>
<user username="Kukuk1">
</user>
<user username="Kukuk2">
</user>
<user username="Kukuk3">
  </user>
</users>
<bids>
  <product id="1">
    <bid user="Kukuk1">400</bid>
    <bid user="Kukuk2">410</bid>
    <bid user="Kukuk1">450</bid>
  </product>
  <product id="2">
    <bid user="Kukuk3">200</bid>
    <bid user="Kukuk2">300</bid>
  </product>
  <product id="3">
    <bid user="Kukuk1">150</bid>
  </product>
</bids>
</auctions>

我需要获得此输出,如下所示:用户“Kukuk1”获得产品“Name1”(值为“450”)和“Name3”(值为“150”)。用户“Kukuk3”没有赢得了所有产品。用户“Kukuk2”赢得了产品“Name2”。

元素应按用户升序排序,元素乘积递减,应如下所示:

 <got>
  <user name="Kukuk1">
    <product value="450">Name1</product>
    <product value="150">Name3</product>
  </user>
  <user name="Kukuk3"/>
  <user name="Kukuk2">
    <product value="300">Name2</product>
  </user>
 </got>

这是我到目前为止所得到的:

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:item-separator "&#xa;";
 <got>&#xa;{
  for $u in (//auctions/users/user)
   let $p:= //auctions/products
   let $v := //auctions/bids/product
   let $max1 := max($v/bid)
   let $max2 := max($v/bid[4])
   let $got := //auctions/bids/product
   let $won-product := $got[@id=$p/product/@id]
   order by $u
   return 
      if ($u/@username="Kukuk1") then
              (<user name="{fn:string($u/@username)}"> 
&#xa;<product value="{$max1}">{fn:string($p/product[1]/name)}</product>
&#xa;</user>,'&#xa;')
        else
            if 
            ($u/@username="Kukuk3") then
                (<user name="{fn:string($u/@username)}"> &#xa;<product value="{$max2}">{fn:string($p/product[2]/name)}</product>&#xa;</user>,'&#xa;')
            else
                if
                    ($u/@username="Kukuk2") then
                        (<user name="{fn:string($u/@username)}">
 &#xa;<product value="{$max2}">{fn:string($p/product[3]/name)}</product>&#xa;
 </user>,'&#xa;')
                else ()

}
</got>

我得到了这个输出:

<got>
 <user name="Kukuk1"> 
  <product value="450">Name1</product>
 </user>
 <user name="Kukuk3"> 
  <product value="">Name2</product>
 </user>
 <user name="Kukuk2"> 
  <product value="">Name3</product>
 </user>
</got>

1 个答案:

答案 0 :(得分:0)

您将需要两个for循环来实现您描述的结果。在外部循环中,您将根据用户的用户名对用户进行排序,在内部循环中,您将获得出价并按其最高价值进行排序。

因此,它应该看起来像这样:

<got>{
  for $u in //auctions/users/user
  let $username := $u/@username
  order by $username
  return element user {
    $username,
    for $product in //auctions/bids/product[bid/@user = $username]
    let $highest-bid := max($product/bid)
    order by $highest-bid descending
    return
      if ($product/bid[. = $highest-bid and @user = $username])
      then element product {
        attribute {"value"} {$highest-bid},
        //auctions/products/product[@id = $product/@id]/name/string()
      } else ()
  }
}</got>

请注意,您的示例输出不符合您的说明Kukuk3 > Kukuk2,因此应按此顺序排序。我认为你的描述是正确的。