2015-10-03 2 views
4

Я знаю, что граф функция может быть использована для подсчета количества элементов в заданной последовательности, например:XQuery: Как подсчитать, сколько раз значение происходит в последовательности

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="">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.

Как я могу создать этот список?

PS: Конечная цель - найти актеров, которые появились в большинстве фильмов.

+1

Индекс-оф Функция xpath может использоваться в сочетании с функцией count. Из спецификации w3c: Summary: Возвращает последовательность положительных целых чисел, дающую позиции в последовательности $ seqParam элементов, которые равны $ srchParam. – pgfearo

+0

@pgfearo, Да, см. Мой ответ. –

ответ

3

Это вопрос, который не подходит для хранилища документов, когда вы просто сохраняете список участников в видео. Я бы предложил также сохранить списки видеороликов, частью которых является актер. Тогда вам просто нужно будет запросить актера, у которого есть большинство элементов видео.

Все, что сказано, вы можете сделать это с данными, которые у вас есть, это будет не так быстро. Сначала вам нужно получить список участников. Затем запрос для каждого актера фильтрует видео, которые имеют этот актер, и делает подсчет. а затем упорядочить по счету.

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) 
0

ответ Тайлер является лучшим решением для того, что вы в конечном итоге пытаетесь достичь, так что я бы с этим, но для ответа на конкретный вопрос о том, как подсчитать, сколько раз значение происходит в последовательность: вы можете использовать предикат последовательности, чтобы создать новую последовательность, содержащую только те значения, которые соответствуют одному вы заботитесь о, а затем подсчитать, что:

let $actors := result/videos//actorRef 
for $actor in distinct-values($actors) 
return 
    ($actor, count($actors[. = $actor])) 
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 (собственное подмножество XQu 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]] 
Смежные вопросы