Если порядок нужно «перетасовать», но не случайно...
(Обновление: см. другой мой ответ для получения более гибкого и рандомизируемого решения.)
Вы говорите «случайный» порядок, который вы получаете при вызове ORDER BY random()
— для каждой строки PostgreSQL вызывает random()
, получает значение и использует его, чтобы решить, как сортировать эту строку в наборе результатов.
Чтобы сделать это повторяемым, вы должны возиться с семенами. Это неприятно. Согласно документам:
эффекты будут сохраняться до конца сеанса, если только они не будут переопределены другим SET
Я думаю, это означает, что при использовании пула соединений setseed
изменяет соединение для следующего процесса, который использует это соединение.
А по модулю?
У меня есть случай, когда мне не нужна настоящая случайность. Мои критерии:
- не тот же порядок каждый раз
- предсказуемый порядок на страницах одного и того же набора результатов, чтобы мы не получали дубликаты на последующих страницах
Например, это было бы хорошо:
- Listing 1
- page 1: items 1, 4
- страница 2: пункты 3, 2
- Listing 2 (different user, or same user coming back later)
- page 1: items 3, 1
- стр. 2: пункты 2, 4
Чтобы получить что-то подобное, модуль работает хорошо. Например, ORDER BY id % 7, id
для всех страниц запроса 1 и ORDER BY id % 11, id
для всех страниц запроса 2. То есть для каждой строки разделите ее идентификатор на модуль и отсортируйте по остатку. В строках с одинаковым остатком отсортируйте по идентификатору (чтобы обеспечить стабильность сортировки).
Модуль может быть выбран случайным образом для первой страницы, а затем повторно использоваться в качестве параметра для каждого последующего запроса страницы.
Вы можете увидеть, как это может работать для вашей базы данных, например:
echo "select id, id % 7 FROM my_table ORDER BY id % 77, id" | psql my_db > sort.txt
Простой модуль, вероятно, даст вам наибольшее разнообразие. И если ваши идентификаторы начинаются с 1 (так что % 77
заставит первые 77 строк возвращаться в обычном порядке), вы можете вместо этого попробовать выполнить модуль в поле метки времени. Например:
ORDER BY (extract(epoch from inserted_at)* 100000)::bigint % 77
Но вам понадобится индекс функции, чтобы сделать это производительным.
person
Nathan Long
schedule
02.10.2017
OREDER BY random()
обычно не очень хорошая идея .com/questions/8674718/ - person pozs   schedule 25.08.2014