Я думаю, что стандартизированная функция random-numer-generator
и ее функция permute
(https://www.w3.org/TR/xpath-functions/#func-random-number-generator) должны дать вам лучшую "случайность" и разнообразные результаты, например
let $file-count := count($data)
return $data[position() = random-number-generator(current-dateTime())?permute(1 to $file-count)[position() le 4]]
Я не пробовал этогос вашей реализацией db / XQuery, и, возможно, существуют способы использования функций, которые вы используете в настоящее время.
Для eXist-db, я полагаю, одной из стратегий является вызов функции random-number
, пока вы не получите четкую последовательностьиз искомого числа значений следующие возвращают (по крайней мере, в некоторых тестах с eXide)) четыре различных числа от 1 до 40 при каждом вызове:
declare function local:random-sequence($max as xs:integer, $length as xs:integer) as xs:integer+ {
local:random-sequence((), $max, $length)
};
declare function local:random-sequence($seq as xs:integer*, $max as xs:integer, $length as xs:integer) as xs:integer+ {
if (count($seq) = $length and $seq = distinct-values($seq))
then $seq
else local:random-sequence((distinct-values($seq), util:random($max)), $max, $length)
};
let $file-count := 40
return local:random-sequence($file-count, 4)
Интегрирование, которое в предыдущей попытке привело бы к
let $file-count := count($data)
return $data[position() = local:random-sequence($file-count, 4)]
Что касается вашего комментария, я не заметил, что существующая util:random
функция может возвращать 0 и исключает максимальное значение, поэтому на основании вашего комментария и дальнейшего теста, я думаю, вы скорее хотите, чтобы функция, которую я опубликовалвыше должно быть реализовано как
declare function local:random-sequence($seq as xs:integer*, $max as xs:integer, $length as xs:integer) as xs:integer+ {
if (count($seq) = $length)
then $seq
else
let $new-number := util:random($max + 1)
return if ($seq = $new-number or $new-number = 0)
then local:random-sequence($seq, $max, $length)
else local:random-sequence(($seq, $new-number), $max, $length)
};
Таким образом, мы надеемся, что теперь он возвращает $length
различные значения между 1
и аргументом $max
.