只在一个查询中获取没有ORDER BY RAND()的RAND()行

时间:2010-07-22 16:23:21

标签: mysql random query-optimization

在MySQL中使用RAND()从巨大的表中获取单个随机行非常慢:

SELECT quote FROM quotes ORDER BY RAND() LIMIT 1

Here is an article关于此问题及其原因。

他们的解决方案是使用两个查询:

SELECT COUNT(*) AS cnt FROM quotes

- Use result to generate a number between 0 and COUNT(*)

SELECT quote FROM quotes LIMIT $generated_number, 1

我想知道,这是否只能在一个查询中实现。

所以我的方法是:

SELECT * FROM quotes
LIMIT (
  ROUND(
    (SELECT COUNT(*) FROM quotes) * RAND()
  )
), 1

但它接缝MySQL不允许在Limit内的任何逻辑。 虽然我找不到关于这个主题的任何信息,但是否属实。

所以我的问题:

  1. 如何在LIMIT中使用RAND()?
  2. 你知道其他任何方式 只用一个查询来解决这个问题吗?

3 个答案:

答案 0 :(得分:5)

是否有理由不能使用存储过程来创建预准备语句?

DELIMITER //
DROP PROCEDURE IF EXISTS rand_quote//
CREATE PROCEDURE rand_quote()
BEGIN
    SET @rand := ROUND((SELECT COUNT(*) FROM quotes) * RAND());
    SET @sql := CONCAT('SELECT * FROM quotes LIMIT ', @rand, ', 1');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END;
//
DELIMITER ;

答案 1 :(得分:1)

我只是想到了这个,接缝就像一个解决方案:

SELECT * FROM quotes
WHERE quotes_id = ROUND(
  (SELECT COUNT(*) FROM quotes) * RAND()
)
LIMIT 1

但只有当quotes_id没有间隙时才会起作用。

答案 2 :(得分:1)

我通过检查max id解决了这个问题。然后我做了rand(0,max_id)的php循环,它检查对象是否存在。完成。

比之前的兰德订购快得多。