D A T Y P I C
XQuery

XQuery

Priscilla Walmsley (pwalmsley@datypic.com)
ISBN: 0596006349
1st edition, 2007, O'Reilly Media, Inc.
Amazon.com
Buy at 37% off list price


Chapter 6: Selecting and Joining Using FLWORs

Example 6-1. FLWOR

for $prod in doc("catalog.xml")//product
let $prodDept := $prod/@dept
where $prodDept = "ACC" or $prodDept = "WMN"
return $prod/name


Example 6-2. Using a range expression

for $i in 1 to 3
return <oneEval>{$i}</oneEval>


Example 6-3. Multiple for clauses

for $i in (1, 2)
for $j in ("a", "b")
return <oneEval>i is {$i} and j is {$j}</oneEval>


Example 6-4. Multiple variable bindings in one for clause

for $i in (1, 2), $j in ("a", "b")
return <oneEval>i is {$i} and j is {$j}</oneEval>


Example 6-5. Using a let clause with a range expression

let $i := (1 to 3)
return <oneEval>{$i}</oneEval>


Example 6-6. Intermingled for and let clauses

let $doc := doc("catalog.xml")
for $prod in $doc//product
let $prodDept := $prod/@dept
let $prodName := $prod/name
where $prodDept = "ACC" or $prodDept = "WMN"
return $prodName


Example 6-7. A where clause with multiple expressions

for $prod in doc("catalog.xml")//product
let $prodDept := $prod/@dept
where $prod/number > 100
      and starts-with($prod/name, "F")
      and exists($prod/colorChoices)
      and ($prodDept = "ACC" or $prodDept = "WMN")
return $prod


Example 6-8. Quantified expression using the some keyword

some $dept in doc("catalog.xml")//product/@dept
satisfies ($dept = "ACC")


Example 6-9. Quantified expression using the every keyword

every $dept in doc("catalog.xml")//product/@dept
satisfies ($dept = "ACC")


Example 6-10. Combining the not function with a quantified expression

not(some $dept in doc("catalog.xml")//product/@dept
    satisfies ($dept = "ACC"))


Example 6-11. Binding multiple variables in a quantified expression

some $i in (1 to 3), $j in (10, 11)
  satisfies $j - $i = 7


Example 6-12. Distinctness on a combination of values

let $prods := doc("catalog.xml")//product
for $d in distinct-values($prods/@dept),
    $n in distinct-values($prods[@dept = $d]/number)
return <result dept="{$d}" number="{$n}"/>


Example 6-13. Two-way join in a predicate

for $item in doc("order.xml")//item,
    $product in doc("catalog.xml")//product[number = $item/@num]
return <item num="{$item/@num}"
             name="{$product/name}"
             quan="{$item/@quantity}"/>


Example 6-14. Two-way join in a where clause

for $item in doc("order.xml")//item,
    $product in doc("catalog.xml")//product
where $item/@num = $product/number
return <item num="{$item/@num}"
             name="{$product/name}"
             quan="{$item/@quantity}"/>


Example 6-15. Three-way join in a where clause

for $item in doc("order.xml")//item,
    $product in doc("catalog.xml")//product,
    $price in doc("prices.xml")//prices/priceList/prod
where $item/@num = $product/number and $product/number = $price/@num
return <item num="{$item/@num}"
             name="{$product/name}"
             price="{$price/price}"/>


Example 6-16. Outer join

for $product in doc("catalog.xml")//product
return <product number="{$product/number}">{
                attribute price
                   {for $price in doc("prices.xml")//prices/priceList/prod
                    where $product/number = $price/@num
                    return $price/price}
  }</product>


Useful Function. distinct-deep (see also functx:distinct-deep)

declare namespace functx = "http://www.functx.com";
declare function functx:distinct-deep ($nodes as node()*) as node()*
 {
   for $x in (1 to count($nodes))
   let $node := $nodes[$x]
   let $restOfNodes := subsequence($nodes, $x + 1)
   return if (some $otherNode in $restOfNodes satisfies
              (deep-equal($otherNode, $node)))
          then ()
          else $node
 };

(: Example call :)
functx:distinct-deep(doc("catalog.xml")//product)