let $s := document("emp.xml")//entry[dname = $d and salary .<. 70000]/salary
where not(exists($s))
return
<deptavg>
$d,
<avgsal> avg(document("emp.xml")//entry[dname = $d]/salary) </avgsal>
</deptpayroll>
</specialdepartments>
这同时也说明了sql语法的不完善性,计算机科学技术系的学生必须十分重视对这个的认识。当一个事情被标准化后会引来多大的麻烦。而xquery在最开始的时候就被设计的非常好。kweelt 的不完善性可能源于预标准化版本的xquery。
排序
排序是被默认执行的。如下例所示:
for $i in (1, 2),
$j in (3, 4)
return
<tuple>
<i>{ $i }</i>
<j>{ $j }</j>
</tuple>
结果输出的格式如下,顺序是非常重要的。
<tuple> <i>1</i> <j>3</j> </tuple>
<tuple> <i>1</i> <j>4</j> </tuple>
<tuple> <i>2</i> <j>3</j> </tuple>
<tuple> <i>2</i> <j>4</j> </tuple>
当然,我们为了效率也可以改变顺序,如下例所示:输出的结果与上面类似,但是顺序可能是不一样的,系统将进行优化。
for $i in unordered(1, 2),
$j in unordered(3, 4)
return
<tuple>
<i>{ $i }</i>
<j>{ $j }</j>
</tuple>
重构
考虑下面的一个例子,这个例子是关于书的,每一本书包含作者和出版商的信息。
<bib>
<book>
<title>tcp/ip illustrated</title>
<author>w. stevens</author>
<publisher>addison-wesley</publisher>
</book>
<book>
<title>advanced programming in the unix environment</title>
<author>w. stevens</author>
<publisher>addison-wesley</publisher>
</book>
</bib>
下面的表达式用来将输入转换成一个作者列表:
<authlist>
{
let $input := document("bib.xml")
for $a in distinct-values($in//author)
return
<author>
{
<name>
{ $a/text() }
</name>,
<books>
{
for $b in $input//book
where $b/author = $a
return $b/title
}
</books>
}
</author>
}
</authlist>
可以发现:作者表中列出的是作者的姓名,每一个作者元素都包括了作者的姓名以及作者的著作名称,其中使用了distinct-values来防止输出顺序遭破坏。
下面是表达式输出的结果:
<authlist>
<author>
<name>w. stevens</name>
<books>
<title>tcp/ip illustrated</title>
<title>advanced programming in the unix environment</title>
</books>
</author>
</authlist>
进行数据查询程序编写的程序员应当谨慎将flwr表达式同路径表达式组合使用。最为重要的是你必须清除路径表达式的返回结果是按照文档顺序的,而flwr 表达式的返回结果是由for语句决定的。
查找
下面的例子列出了价格大于100的书,按照第一作者的名字来查找,每个作者又按照标题来查找。
//book[price > 100] sortby (author[1], title)
排序可以产生多级查找结果,下面的查询返回了一个按照字母顺序排出的出版商列表,在每一个出版商元素中包含了若干的书元素,每一个数元素都包含书的名称和价格,而且是按照降序排列的。
<publisher_list>
{for $p in distinct-values(document("bib.xml")//publisher)
return
<publisher>