Chapter 15: Principles of Query Design
Example 15-1. Making use of whitespace
Less Clear Query
for $product in doc("catalog.xml")//product return
<product><number>{$product/number}</number>
<price>{for $price in doc("prices.xml")//prod
where $product/number = $price/@num
return $price/price}</price>
</product>
More Clear Query
for $product in doc("catalog.xml")//product
return <product>
<number>{$product/number}</number>
<price>{for $price in doc("prices.xml")//prod
where $product/number = $price/@num
return $price/price}</price>
</product>
Example 15-2. Documenting a function with xqdoc
(:~
: The <b>functx:substring-after-last</b> function returns the part
: of <b>$string</b> that appears after the last occurrence of
: <b>$delim</b>. If <b>$string</b> does not contain
: <b>$delim</b>, the entire string is returned.
:
: @param $string the string to substring
: @param $delim the delimiter
: @return the substring
:)
declare function functx:substring-after-last
($string as xs:string?, $delim as xs:string) as xs:string?
{ ... };
Example 15-3. Avoid re-evaluating the same expression
Less Efficient Query
if (doc("prices.xml")/prices/priceList/prod[price < 30])
then <bargain-bin>{
doc("prices.xml")/*/priceList/prod[price < 30]
}</bargain-bin>
else ()
More Efficient Query
let $bargains := doc("prices.xml")/prices/priceList/prod[price < 30]
return if ($bargains)
then <bargain-bin>{$bargains}</bargain-bin>
else ()
Example 15-4. Avoid unnecessary sorting
Less Efficient Query
let $doc := doc("catalog.xml")
return $doc//number | $doc//name
More Efficient Query
unordered {
let $doc := doc("catalog.xml")
return $doc//(number|name)
}
Example 15-5. Avoid expensive path expressions
Less Efficient Query
doc("catalog.xml")//number
More Efficient Query
doc("catalog.xml")/catalog/product/number
Example 15-6. Use predicates instead of where clauses
Less Efficient Query
for $prod in doc("catalog.xml")//product
where $prod/@dept = "ACC"
order by $prod/name
return $prod/name
More Efficient Query
for $prod in doc("catalog.xml")//product[@dept = "ACC"]
order by $prod/name
return $prod/name
Useful Function. if-absent (see also functx:if-absent)
declare namespace functx = "http://www.functx.com";
declare function functx:if-absent (
$node as node()?, $value as xs:anyAtomicType) as xs:anyAtomicType*
{
if ($node)
then data($node)
else $value
};
(: Example call :)
for $prod in doc("prices.xml")//prod
return $prod/price - functx:if-absent($prod/discount, 0)
Useful Function. if-empty (see also functx:if-empty)
declare namespace functx = "http://www.functx.com";
declare function functx:if-empty (
$node as node()?, $value as xs:anyAtomicType) as xs:anyAtomicType*
{
if (string($node) != "")
then data($node)
else $value
};
(: Example call :)
for $prod in doc("prices.xml")//prod
return $prod/price - functx:if-empty($prod/discount, 0)
|