我正在尝试在XQuery中实现动态排序。我目前正在使用Saxon-PE 9.5进行开发,但是将在eXist和marklogic中使用XQuery(或xqueries复数),因此使用其模块/功能的所有答案都很好(希望其他数据库具有相应的模块/功能) 。

排序基于包含字符串序列的变量。序列中的每个字符串都是元素的名称和可选的“降序”。

我已经尝试了多种方法,但是无法按照预期的方式工作。特别是对于次要排序。

在下面的示例中,排序是静态的,主要类型为c(升序),次要类型为b(降序)...

so_xquery_question.xml

<doc>
    <foo id="foo1">
        <a>a1</a>
        <b>b1</b>
        <c>c0</c>
    </foo>
    <foo id="foo2">
        <a>a2</a>
        <b>b2</b>
        <c>c0</c>
    </foo>
    <foo id="foo3">
        <a>a3</a>
        <b>b3</b>
        <c>c3</c>
    </foo>
</doc>

XQuery
let $xml := doc('file:///C:/SO/so_xquery_question.xml')

return
<test>{
for $foo in $xml/doc/foo
order by $foo/c, $foo/b descending
return
    $foo
}</test>

输出
<test>
   <foo id="foo2">
        <a>a2</a>
        <b>b2</b>
        <c>c0</c>
    </foo>
   <foo id="foo1">
        <a>a1</a>
        <b>b1</b>
        <c>c0</c>
    </foo>
   <foo id="foo3">
        <a>a3</a>
        <b>b3</b>
        <c>c3</c>
    </foo>
</test>

输出已正确排序;首先按c(升序),然后按b(降序)。

我最近的尝试部分起作用。 (在Saxon和marklogic中。由于某些未知原因(!@#$),它在eXist中的工作方式不同。)

这里是:

XQuery
let $orderby := ('c','b descending')
let $xml := doc('file:///C:/SO/so_xquery_question.xml')

return
<test>{
for $foo in $xml/doc/foo
order by
    if ($orderby='b') then $foo/b else (),
    if ($orderby='b descending') then $foo/b else () descending,
    if ($orderby='c') then $foo/c else (),
    if ($orderby='c descending') then $foo/c else () descending
    return
        $foo
}</test>

输出
<test>
   <foo id="foo3">
        <a>a3</a>
        <b>b3</b>
        <c>c3</c>
    </foo>
   <foo id="foo2">
        <a>a2</a>
        <b>b2</b>
        <c>c0</c>
    </foo>
   <foo id="foo1">
        <a>a1</a>
        <b>b1</b>
        <c>c0</c>
    </foo>
</test>

如您所见,它首先在b上排序(降序)。这是因为那是iforder by语句的顺序;不在变量序列的顺序上($orderby)。如果我交换if的顺序(首先测试c),则排序很好。

我也在eXist中工作,但它无法处理descending:
order by util:eval(concat('$foo/',string-join(tokenize($orderby,'\s')[1],', $foo/')))

有什么办法可以进行考虑以下因素的动态排序?
  • 可以传递元素名称作为变量进行排序。
  • 可以为变量中的元素名称指定可选的“降序”。
  • 维护变量的顺序(主要排序与次要排序)。
  • 最佳答案

    这是XQuery 1.0中的一个漏洞,我不认为3.0可以解决此问题。

    对于非评估方法,您是否尝试过类似的方法?

    if ($orderby='b') then $foo/b
    else if ($orderby='c') then $foo/c else (),
    if ($orderby='b descending') then $foo/b
    else if ($orderby='c descending') then $foo/c else () descending
    

    但是,我可能会将键和方向分为两个不同的变量。

    关于xml - XQuery中基于变量的动态排序(排序依据),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23769228/

    10-09 15:46
    查看更多