Xquery 顶部函数

发布于 2024-10-01 19:29:42 字数 648 浏览 0 评论 0原文

我怎样才能使用Xquery实现类似于SQL的TOP功能?换句话说,如何选择有联系的前 5 个元素?这应该很简单,但我在谷歌上找不到它。

我可能想要格式化的一些数据的示例如下所示:

<?xml version="1.0"?>
<root>
    <value> 
        <a>first</a>
        <b>1</b>
    </value>
    <value> 
        <a>third</a>
        <b>3</b>
    </value>
    <value> 
        <a>second</a>
        <b>2</b>
    </value>
    <value> 
        <a>2nd</a>
        <b>2</b>
    </value>
</root>

我想按 b 对所有值进行排序并返回 a。为了说明我的问题,假设我想返回带联系的前两个值。

谢谢

How can I achieve something similar to the TOP function is SQL using Xquery? In other words, how can I select the top 5 elements of something with ties? This should be simple but I'm having trouble finding it with Google.

An example of some data I might want to format looks like this:

<?xml version="1.0"?>
<root>
    <value> 
        <a>first</a>
        <b>1</b>
    </value>
    <value> 
        <a>third</a>
        <b>3</b>
    </value>
    <value> 
        <a>second</a>
        <b>2</b>
    </value>
    <value> 
        <a>2nd</a>
        <b>2</b>
    </value>
</root>

I want to sort by b for all of the values and return a. To illustrate my problem, say I want to return the top two values with ties.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

a√萤火虫的光℡ 2024-10-08 19:29:42

对于提供的源 XML 文档

<root>
  <value> 
    <a>first</a>
    <b>1</b>
  </value>
  <value> 
    <a>third</a>
    <b>3</b>
  </value>
  <value> 
    <a>second</a>
    <b>2</b>
  </value>
  <value> 
    <a>2nd</a>
    <b>2</b>
  </value>
</root>

要获得“有联系”的前两个结果,请使用

let $vals := 
  for $k in distinct-values(/*/*/b/xs:integer(.)) 
    order by $k
    return $k
 return
  for $a in /*/value[index-of($vals,xs:integer(b)) le 2]/a
      order by $a/../b/xs:integer(.)
    return $a  

计算此表达式时,会生成所需的正确结果< /strong>:

<a>first</a>
<a>second</a>
<a>2nd</a>

解释:

  1. 我们在 $vals 中指定 /*/*/b 的所有不同值的排序序列code>,用作整数。这是必要的,因为函数 distinct- value() 不保证以任何预定义的顺序生成其结果序列。此外,如果我们在排序之前不将值转换为 xs:integer,它们将被排序为字符串,这通常会产生不正确的结果。

  2. 然后,我们仅选择那些 /*/value/a,其 b-sibling 在不同整数 b-values 的排序序列中的索引小于或等于到 2

  3. 最后,我们需要按 b 兄弟的整数值对结果进行排序,否则它们将按照文档顺序进行选择

请注意

目前只有此解决方案为 /*/*/b 的任何整数值生成正确排序的结果

For the provided source XML document:

<root>
  <value> 
    <a>first</a>
    <b>1</b>
  </value>
  <value> 
    <a>third</a>
    <b>3</b>
  </value>
  <value> 
    <a>second</a>
    <b>2</b>
  </value>
  <value> 
    <a>2nd</a>
    <b>2</b>
  </value>
</root>

To get the first two results "with ties" use:

let $vals := 
  for $k in distinct-values(/*/*/b/xs:integer(.)) 
    order by $k
    return $k
 return
  for $a in /*/value[index-of($vals,xs:integer(b)) le 2]/a
      order by $a/../b/xs:integer(.)
    return $a  

When this expression is evaluated, the wanted, correct result is produced:

<a>first</a>
<a>second</a>
<a>2nd</a>

Explanation:

  1. We specify in $vals the sorted sequence of all distinct values of /*/*/b, used as integers. This is necessary, because the function distinct-values() is not guaranteed to produce its result sequence in any predefined order. Also, if we do not convert the values to xs:integer before sorting, they would be sorted as strings and this would generally produce incorrect results.

  2. Then we select only those /*/value/a whose b-sibling's index in the sorted sequence of distinct integer b-values is less or equal to 2.

  3. Finally, we need to sort the results by their b-sibling's integer values, because otherwise they will be selected in document order

Do note:

Only this solution at present produces correctly sorted results for any integer values of /*/*/b.

策马西风 2024-10-08 19:29:42

要过滤序列到前 5 个项目,请使用 fn:position() 函数:

$sequence[position() le 5]

请注意,当要过滤的序列是 / 步骤的节点集结果时操作时,谓词针对最后一个轴起作用。因此,也许您需要将该表达式括在括号之间。

但是,要过滤“计算序列”(如排序或元组过滤条件),您需要使用 FLWOR 表达式的全部功能。

此 XQuery:

(for $value in /root/value
 order by $value/b
 return $value/a)[position() le 2]

输出:

<a>first</a><a>second</a>

注意:这是一个简单的排序。过滤器是最外层的表达式,因为这允许延迟求值。

此 XQuery:

for $key in (for $val in distinct-values(/root/value/b)
             order by xs:integer($val)
             return $val)[position() le 2]
return /root/value[b=$key]/a

输出:

<a>first</a><a>second</a><a>2nd</a>

注意:首先对键进行排序,然后返回前两个键的所有结果。

编辑:添加显式整数转换。

To filter a sequence to the first 5 items you use the fn:position() function:

$sequence[position() le 5]

Do note that when the sequence to filter is a node set resultion from an / step operation, the predicate works againts the last axis. So, maybe you would need to wrap that expression between parentesis.

But, to filter a "calculated sequence" (like sorting or tuples filter conditions), you need to use the full power of the FLWOR expression.

This XQuery:

(for $value in /root/value
 order by $value/b
 return $value/a)[position() le 2]

Output:

<a>first</a><a>second</a>

Note: This is a simple sort. The filter is the outer most expression because this allows lazy avaluation.

This XQuery:

for $key in (for $val in distinct-values(/root/value/b)
             order by xs:integer($val)
             return $val)[position() le 2]
return /root/value[b=$key]/a

Output:

<a>first</a><a>second</a><a>2nd</a>

Note: This order the keys first an then return all the result for the first two keys.

Edit: Added explicit integer casting.

最近可好 2024-10-08 19:29:42

您可以在具有上限的节点上使用 XPath 作为索引

    <one>
  <two>a</two>
  <two>b</two>
  <two>c</two>
  <two>d</two>
  <two>e</two>
  <two>f</two>
  <two>g</two>
  <two>h</two>
   </one>

然后

$xml_data/one/two[ 1 to 5 ]

$xml_data/one/two[ some_number to fn:last() ]

You can use XPath on the Node with top limit as indexes

    <one>
  <two>a</two>
  <two>b</two>
  <two>c</two>
  <two>d</two>
  <two>e</two>
  <two>f</two>
  <two>g</two>
  <two>h</two>
   </one>

Then

$xml_data/one/two[ 1 to 5 ]

$xml_data/one/two[ some_number to fn:last() ]
九歌凝 2024-10-08 19:29:42

使用示例输入

<one>
  <two>a</two>
  <two>b</two>
  <two>c</two>
  <two>d</two>
  <two>e</two>
  <two>f</two>
  <two>g</two>
  <two>h</two>
</one>

以下是获取前五行的一种方法:

for $two at $index in /one/two
  where $index <= 5
  return $two

With sample input

<one>
  <two>a</two>
  <two>b</two>
  <two>c</two>
  <two>d</two>
  <two>e</two>
  <two>f</two>
  <two>g</two>
  <two>h</two>
</one>

The following is one way to get the first five rows:

for $two at $index in /one/two
  where $index <= 5
  return $two
人│生佛魔见 2024-10-08 19:29:42

在 MySQL 方言中,它不称为 TOP,而是称为 LIMIT。当您在 google 上搜索“limit xquery”时,您会发现:

http:// /osdir.com/ml/text.xml.exist/2004-02/msg00214.html

http://osdir.com/ml/text.xml.exist/2004-08/msg00115.html

In the MySQL dialect it's not called TOP, but LIMIT. When you google for "limit xquery" you will find:

http://osdir.com/ml/text.xml.exist/2004-02/msg00214.html

and

http://osdir.com/ml/text.xml.exist/2004-08/msg00115.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文