Задать вопрос
@kr_ilya

Как быстро выбрать случайные записи postgresql?

Нужно выбрать определенное количество случайных записей, например 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, хотя все остальные значения соответствуют условию. И так при каждой выборке.

Может есть куда более лучшие практики получения рандомных строк по определенному условию с нормальным рандомом?
  • Вопрос задан
  • 193 просмотра
Подписаться 2 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 2
dimonchik2013
@dimonchik2013
non progredi est regredi
@Fenrir89
postgres=# SELECT floor(random()*(10-1+1))+1;
?column?
----------
8
(1 row)

Пример выдачи целочисленого рандома, в твоём коде он должен возвращать дробное число
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы