我知道函数计数可用于计算给定序列中元素的数量,如下所示:
count(result/actors/actor)
在这个XML中:
<result>
<actors>
<actor id="00000015">Anderson, Jeff</actor>
<actor id="00000030">Bishop, Kevin</actor>
<actor id="0000000f">Bonet, Lisa</actor>
<actor id="916503207">Parillaud, Anne</actor>
<actor id="916503208">Pitt, Brad</actor>
<actor id="916503209">Freeman, Morgan</actor>
<actor id="916503211">Domingo, Placido</actor>
<actor id="916503210">Sharif, Omar</actor>
<actor id="1337">Doqumenteriet2011</actor>
</actors>
</result>
但是如果我想知道给定序列中出现的值多少次呢?
例如,如果我想知道每个演员(actorRef)在以下XML中出现了多少部电影:
<videos>
<video id="id1235AA0">
<title>The Fugitive</title>
<actorRef>00000003</actorRef>
<actorRef>00000006</actorRef>
</video>
<video id="id1244100">
<title>Enemy of the State</title>
<actorRef>00000009</actorRef>
<actorRef>0000000c</actorRef>
<actorRef>0000000f</actorRef>
<actorRef>00000012</actorRef>
</video>
<video id="id124E230">
<title>Clerks</title>
<actorRef>00000015</actorRef>
<actorRef>00000018</actorRef>
<actorRef>0000001b</actorRef>
</video>
我可以很容易地生成所有出现的演员的列表,甚至可以在我生成的序列中出现多次,就像在XML中一样:
result/videos//actorRef
但我无法做任何类似于例如COUNT()和GROUP BY在SQL中一起做的事情,以通过上述XQuery行生成的序列中的多重性计数来获取actor的列表。 / p>
如何制作此列表?
PS:最终目标是找到出现最多电影的演员。
答案 0 :(得分:3)
当您只是在视频中存储演员列表时,这是一种对文档存储不利的问题。我建议还存储一个演员所属的视频列表。然后你只需要查询拥有最多视频元素的actor。
所有这一切,你可以用你拥有的数据来做它只是不会那么快。首先需要获得演员的距离列表。然后查询每个演员过滤具有该演员的视频并进行计数。然后按计数排序。
let $actors := fn:distinct-values($results/videos/video/actorRef)
for $actor in $actors
let $count := fn:count($results/videos/video[actorRef = $actor])
Order by $count
return ($actor, $count)
答案 1 :(得分:3)
这是一个纯XPath 2.0表达式(XPath 2.0是XQuery的正确子集),生成actorRef
值序列,用于标识参与最大数量的参与者电影:
for $maxMovies in
max(for $actorId in distinct-values(/*/*/actorRef)
return
count(index-of(/*/*/actorRef, $actorId))
)
return
(/*/*/actorRef)[index-of(/*/*/actorRef, .)[$maxMovies]]/string()
在以下源XML文档上评估此表达式时:
<videos>
<video id="id1235AA0">
<title>The Fugitive</title>
<actorRef>00000003</actorRef>
<actorRef>00000009</actorRef>
<actorRef>0000000x</actorRef>
</video>
<video id="id1244100">
<title>Enemy of the State</title>
<actorRef>00000009</actorRef>
<actorRef>0000000c</actorRef>
<actorRef>0000000f</actorRef>
<actorRef>00000012</actorRef>
</video>
<video id="id124E230">
<title>Clerks</title>
<actorRef>00000015</actorRef>
<actorRef>00000018</actorRef>
<actorRef>0000001b</actorRef>
</video>
</videos>
产生了正确的,想要的结果:
00000009
使用XPath 3.0(XQuery 3.0的适当子集)甚至可以写得更短:
let $vSeq := /*/*/actorRef/string()
return
for $maxMovies in
max(for $actorId in distinct-values($vSeq)
return
index-of($vSeq, $actorId) ! last()
)
return
$vSeq[index-of($vSeq, .)[$maxMovies]]
这可以使用简单的映射运算符(!
)进一步缩短,以避免任何for-expression
:
let $vSeq := /*/*/actorRef/string(),
$maxOccurs :=
max(distinct-values($vSeq) ! count(index-of($vSeq, .)) )
return
$vSeq[index-of($vSeq, .)[$maxOccurs]]
答案 2 :(得分:0)
Tyler的答案是你最终想要达到的最好的解决方案,所以我会继续这样做,但要回答如何计算序列中值出现次数的具体问题:你可以在序列上使用谓词来创建一个新序列,该序列仅包含与您关注的值匹配的值,然后计算:
let $actors := result/videos//actorRef
for $actor in distinct-values($actors)
return
($actor, count($actors[. = $actor]))