2010-11-24 130 views
1

我对xquery分组有一个问题。从我所了解的情况来看,通常的情况是在for循环中使用distinct-values作为文档,但是因为在分组值之前我有条件满足,所以我不太确定如何做到这一点。Xquery根据条件分组的结果

这是我的XMLDB的一部分:

<element tag="0001,0000" name="Pos1>198</element> 
<element tag="0001,0001" name="Pos2">123</name> 
<element tag="0002,0001" name="Pos3">433</element> 
<element tag="000b,0000" name="Pos3">16</element> 
<element tag="0005,0000" name="Pos4>532</element> 
<element tag="0005,0001" name="Pos5">342</name> 
<element tag="0008,0001" name="Pos6">17</element> 

满足的条件是,x坐标(数或hexdec)必须在奇数值(例如,从上面的XML,我将仅需要结果来自tag =“0001,...”,tag =“000b,...”,tag =“0005,...”),然后计算每个组中有多少项。

这是结果应该什么样子:

<group> 
<element xcoord="0001">2</element> 
<element xcoord="000b">1</element> 
<element xcoord="0005">2</element> 
</group> 

我的XQuery代码到目前为止是这样的,在那里我可以生成具有奇数x坐标的结果,但我不知道如何着手对从这里进行分组。

import module namespace functx="http://www.functx.com" at "http://www.xqueryfunctions.com/xq/functx-1.0-nodoc-2007-01.xq"; 

for $x in collection('/db/mapdb/')//element 
let $coord := number(functx:substring-before-last($x/@tag, ",")) 
where $coord mod 2 != 0 
return $x 

请告诉我。非常感谢你。

+0

问得好,+1。查看我的答案,获得完整和正确的解决方案。 – 2010-11-24 17:19:39

回答

4

这XQuery的

for $x in 
    distinct-values(/*/*/substring-before(@tag,',') 
        [contains('13579bdf', 
           substring(., string-length(.)) 
          ) 
        ] 
       ) 
return 
    <element xcoord="{$x}"> 
    {count(/*/*[$x eq substring-before(@tag,',')])} 
    </element> 

产生想要的,正确的结果

<element xcoord="0001">2</element> 
<element xcoord="000b">1</element> 
<element xcoord="0005">2</element> 
0

你没有说你正在使用哪个处理器。我测试了try.zorba-xquery.com下面的代码(它也应该撒克逊或其他处理器合作支持的XQuery 1.1和XPath 2.0):

let $xmldb := 
    (
    <element tag="0001,0000" name="Pos1">198</element>, 
    <element tag="0001,0001" name="Pos2">123</element>, 
    <element tag="0002,0001" name="Pos3">433</element>, 
    <element tag="000b,0000" name="Pos3">16</element>, 
    <element tag="0005,0000" name="Pos4">532</element>, 
    <element tag="0005,0001" name="Pos5">342</element>, 
    <element tag="0008,0001" name="Pos6">17</element> 
) 
for $x in $xmldb 
let $coord := tokenize($x/@tag, ",")[1] 
group by $coord 
where contains('13579bdf',substring($coord,string-length($coord))) 
return <element xcoord="{$coord}">{count($x)}</element> 

希望帮助?

+0

`其中number($ coord)mod 2!= 0` - 这显然不适用于以十六进制格式表示的数字。 – 2010-11-24 17:26:01

+0

OP可能没有XQuery 3.0处理器,所以这排除了使用`group by`的可能性。 – 2010-11-24 17:26:51

+0

我正在使用eXist DB作为Xquery沙盒,但我认为这个处理器没有按功能分组,这对于SQL来说非常方便。 – 2010-11-25 04:04:03

0

如果使用的XQuery 1.0处理器然后通过一组通常的模式是:

let $values := ... 
for $key in distinct-values(for $value in $values return my:key($value)) 
let $group := $values[my:key(.)=$key] 
return ... 

其中my:key是函数/表达,其获得对于每个输入值的键。

在你的情况,你可以在图案填充像这样:

for $coord in distinct-values($xmldb/(tokenize(.,",")[1])) 
let $x := $xmldb[tokenize(.,",")[1] = $coord] 
return <element xcoord="{$coord}">{count($x)}</element> 

这是否有效地执行取决于具体的实现。我写了一个blog post关于如何编写一个XQSharp将会识别的组。

编辑:我错过了所有x坐标必须是奇数的要求。这可以固定在添加的where子句来约束坐标的最后一个字符:

for $coord in distinct-values($xmldb/(tokenize(.,",")[1])) 
where contains('13579bdf',substring($coord,string-length($coord))) 
let $x := $xmldb[tokenize(.,",")[1] = $coord] 
return <element xcoord="{$coord}">{count($x)}</element> 
3

此的XQuery:

<group>{ 
    for $key in distinct-values(/root/element/tokenize(@tag,',')[1]) 
        [contains('13579bdf',substring(.,string-length(.)))] 
    return <element xcoord="{$key}">{ 
       count(/root/element[tokenize(@tag,',')[1] eq $key]) 
      }</element> 
}</group> 

利用该输入:

<root> 
    <element tag="0001,0000" name="Pos1">198</element> 
    <element tag="0001,0001" name="Pos2">123</element> 
    <element tag="0002,0001" name="Pos3">433</element> 
    <element tag="000b,0000" name="Pos3">16</element> 
    <element tag="0005,0000" name="Pos4">532</element> 
    <element tag="0005,0001" name="Pos5">342</element> 
    <element tag="0008,0001" name="Pos6">17</element> 
</root> 

输出:

<group> 
    <element xcoord="0001">2</element> 
    <element xcoord="000b">1</element> 
    <element xcoord="0005">2</element> 
</group> 

注意:除了eqne之外,没有用于xs:hexBinary数据类型的内置运算符。