@kr_ilya

Как быстро получить рандомную строку из базу postgresql?

Нужно получить рандомную строку из базы.

Из того что есть сейчас:
Медленный:
SELECT * FROM items WHERE sale_price > 100 AND sale_price < 10000 ORDER BY random() LIMIT 1


Быстрее, но никогда не вернет первую запись и у меня бывает вовсе возвращает 0 строк, не могу сказать с чем это связано:
SELECT * FROM items WHERE sale_price > 100 AND sale_price < 10000 OFFSET floor(random() * (SELECT count(*) FROM items)) LIMIT 1

(Источник)

Самый быстрый, взят здесь:
WITH RECURSIVE r AS (
	  WITH b AS (
	    SELECT
	    min(t.id),
	    (
	      SELECT t.id
	      FROM items AS t
	      WHERE
	        t.sale_price > 100 AND
	        t.sale_price < 10000
	      ORDER BY t.id DESC
	      LIMIT 1
	      OFFSET ${custom.numRows} - 1
	    ) max
	    FROM items AS t
	    WHERE 
	      t.sale_price > 100 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 > 100 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 < ${custom.numRows} AND
	      t.sale_price > 100 AND
	      t.sale_price < 10000
	    LIMIT 1
	  )
	)
	SELECT * FROM items AS t, r WHERE r.id = t.id

*custom.numRows = 1
Меня в нем смущает то, что большинство возвращаемых строк приходится на значения id 330-370, выше или ниже этих значений выдает очень редко. Возможно, я где-то накосячил, когда подстраивал этот запрос под свои условия, хз.
Скрин

ORDER BY last_view DESC
5f1a7eb7a6b78389603150.png


Может есть еще варианты быстрого получения рандомной записи? Или может нужно что-то исправить в третьем варианте?
  • Вопрос задан
  • 336 просмотров
Пригласить эксперта
Ответы на вопрос 2
sergey-gornostaev
@sergey-gornostaev Куратор тега PostgreSQL
Седой и строгий
@d-stream
Готовые решения - не подаю, но...
Можно слегка модифицировать ORDER BY random() LIMIT 1 используя его для выборки PK, который уже и использовать в основной выборке

p.s. а какова бизнес-сущность таких рандомных выборок?
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы