Нужно выбрать определенное количество случайных записей, например 10 с условием.
ORDER BY random() становится очень медленным на больших таблицах, а tablesample не подходит, потому что он сначала выбирает строки и уже после применяет условие, из-за этого выборка может быть пустой.
Есть код, который работает быстро, но большинство строк с каждой выборкой приходится на id 600+ и очень редко 1000+.
WITH RECURSIVE r AS (
WITH b AS (
SELECT
min(t.id),
(
SELECT t.id
FROM items AS t
WHERE
t.sale_price > 10 AND
t.sale_price < 10000
ORDER BY t.id DESC
LIMIT 1
OFFSET 5 - 1
) max
FROM items AS t
WHERE
t.sale_price > 10 AND
t.sale_price < 10000
)
(
SELECT
id, min, max, array[]::bigint[] || id AS a, 0 AS n
FROM items AS t, b
WHERE
id >= min + ((max - min) * random())::int AND
t.sale_price > 10 AND
t.sale_price < 10000
LIMIT 1
) UNION ALL (
SELECT t.id, min, max, a || t.id, r.n + 1 AS n
FROM items AS t, r
WHERE
t.id > min + ((max - min) * random())::int AND
t.id <> all( a ) AND
r.n + 1 < 5 AND
t.sale_price > 10 AND
t.sale_price < 10000
LIMIT 1
)
)
SELECT * FROM items AS t, r WHERE r.id = t.id
Источник
При максимальных и минимальных значениях набор id будет такой (массив "a"):
min: '601',
max: '2914',
a: [ '638', '656', '652', '846', '1274' ]
Т.е большинство значений около 600, хотя все остальные значения соответствуют условию. И так при каждой выборке.
Может есть куда более лучшие практики получения рандомных строк по определенному условию с нормальным рандомом?