“for”子句中“where”和“let”子句中“where”之间的XQuery差异

时间:2016-11-10 17:12:54

标签: xml xquery

考虑以下XML:

<bib>
<book year="1994">
    <title>TCP/IP Illustrated</title>
    <author><last>Stevens</last><first>W.</first></author>
<publisher>Addison-Wesley</publisher>
<price>65.95</price>
</book>

<book year="2000">
    <title>Data on the Web</title>
    <author><last>Abiteboul</last><first>Serge</first></author>
    <author><last>Buneman</last><first>Peter</first></author>
    <author><last>Suciu</last><first>Dan</first></author>
    <publisher>Morgan Kaufmann Publishers</publisher>
    <price>39.95</price>
</book>

<book year="1999">
    <title>The Economics of Technology and Content for Digital TV</title>
    <editor><last>Gerbarg</last><first>Darcy</first><affiliation>CITI</affiliation></editor>        
    <publisher>Kluwer Academic Publishers</publisher>
    <price>129.95</price>
</book>
</bib>

我知道以下XQuery查询

for $book in doc(“books.xml”)//book
where $book/price>60
return <expensiveBook>
{ $book/title/text() }
</expensiveBook>

将完全返回两本书的标题,价格大于60:

<expensiveBook>TCP/IP Illustrated</expensiveBook>
<expensiveBook>The Economics of Technology and Content for Digital TV</expensiveBook>

而是以下查询:

let $books := doc(“books.xml”)//book
where $books/price > 60 (: existential... :)
return <expensiveBooks>
{ $books/title }
</expensiveBooks>

将返回XML doc中的全部三本书:

<expensiveBooks>
    <title>TCP/IP Illustrated</title>
    <title>Data on the Web</title>
    <title>The Economics of Technology and Content for Digital TV</title>
</expensiveBooks>

我无法理解为什么会发生这种情况,我不应该将整本书放入用“let”声明的变量中,然后用where子句过滤它吗?为什么它还返回“网上数据”一书,哪个价格低于60?

我无法理解的另一个奇怪的事情是像下面这样的查询:

let $books in doc(“books.xml”)//book[price>60]
return <expensiveBook>
{ $books/title }
</expensiveBook>

正确地只返回价格大于60的两本书:

<expensiveBooks>
    <title>TCP/IP Illustrated</title>
    <title>The Economics of Technology and Content for Digital TV</title>
</expensiveBooks>

这里有什么用?为什么这种行为不符合我的预期呢? where子句对let和for子句的工作方式是否有所不同?那么最后一个查询呢,使用“let”子句但是通过XPath语法指定price元素[element = value]?

感谢您的帮助,一如既往:)

4 个答案:

答案 0 :(得分:1)

我认为您需要在XPath和XQuery上找到一些基本资源。 当你说:

let $books := doc(“books.xml”)//book
where $books/price > 60 (: existential... :)
return <expensiveBooks>
{ $books/title }
</expensiveBooks>

这意味着:将$ books绑定到所有书元素的序列,现在考虑序列中书籍的所有价格元素的顺序:如果它们中的任何一个超过60,则返回所有标题元素的序列$ books中的任何书元素,包含在元素中。所以你得到全部或全部。

你的第一个查询说:迭代这一系列的书元素,如果我现在拥有的价格超过60,则返回标题。

带有XPath约束的查询:

let $books in doc(“books.xml”)//book[price>60]
return <expensiveBook>
{ $books/title }
</expensiveBook>

说:构造一个所有书元素的序列,其元素子元素超过60,并返回一个由这些书的所有标题序列组成的元素,包含在元素中。

让我们绑定一个变量;用于依次将变量绑定到序列的每个成员。序列上的路径表达产生其他序列。 '='和'&gt;'是对序列进行操作并返回单个布尔结果的存在运算符。

答案 1 :(得分:1)

FLWOR表达式的逻辑是它表示元组流,其中元组是(变量名,值)对。 let子句创建一个元组:一个变量,一个值。 for子句创建元组流,为选择中的每个项创建一个元组。 where子句过滤元组流,因此只保留满足条件的那些元组。

如果只有一个元组开始,则使用&#34;过滤&#34;只能是一个元组或没有元组。

答案 2 :(得分:0)

这是因为您没有对序列$books应用约束。这基本上就是如何评估逻辑:Where any book has a price greater than 60, return all books。正如您已经发现的那样,您需要使用XPath谓词来约束序列,或者在XQuery where迭代器中使用for进行约束。

答案 3 :(得分:0)

可能是要使用“ for”而不是“ let”?

使用“ let”,输出如下所述:

输出:

<expensiveBooks>
  <title>TCP/IP Illustrated</title>
  <title>Data on the Web</title>
  <title>The Economics of Technology and Content for Digital TV</title>
</expensiveBooks>

通过更改为“ for”循环,我认为可以获得正确的结果。我将如何以及为什么留给对xquery更为了解的人,但也许注意到这种区别将对您自己或其他人有所帮助。

我的观点是,没有“ for”循环,就永远不会调用“ where”。

输出:

<expensiveBooks>
  <title>TCP/IP Illustrated</title>
</expensiveBooks>
<expensiveBooks>
  <title>The Economics of Technology and Content for Digital TV</title>
</expensiveBooks>

可能您正在考虑使用“ for”?

查询:

xquery version "3.1";

for $books in db:open("bib")//book
where $books/price > 60
return <expensiveBooks>
{ $books/title }
</expensiveBooks>

我将您的xml添加到“围兜”数据库中以供参考,否则与直接引用文档相同。

有趣。