【问题标题】:Selecting random rows with MySQL使用 MySQL 选择随机行
【发布时间】:2011-09-26 08:46:32
【问题描述】:

我看到了很多关于这个主题的话题,但我一直无法理解如何去做。

例如,如果我有这张桌子:

+------+-------+-------+
| id   | name  | class |
+------+-------+-------+
|    5 | test  | one   | 
|   10 | test2 | one   | 
|   12 | test5 | one   | 
|    7 | test6 | two   | 
+------+-------+-------+

我只想显示类“one”中的 X 个随机行,我该怎么做?

注意:这是一张大桌子,所以我不想使用ORDER BY RAND

【问题讨论】:

标签: mysql random


【解决方案1】:

如您所知,大多数人推荐的 ORDER BY RAND() 解决方案无法扩展到大型表。

SET @r := (SELECT FLOOR(RAND() * (SELECT COUNT(*) FROM mytable)));
SET @sql := CONCAT('SELECT * FROM mytable LIMIT 1 OFFSET ', @r);
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

我在我的书 SQL Antipatterns: Avoiding the Pitfalls of Database Programming 中介绍了这个和其他解决方案。


如果你想用 PHP 做到这一点,你可以这样做(未经测试):

<?php
$mysqli->begin_transaction();
$result = $mysqli->query("SELECT COUNT(*) FROM mytable")
$row = $result->fetch_row(); 
$count = $row[0]; 
$offset = mt_rand(0, $count);
$result = $mysqli->query("SELECT * FROM mytable LIMIT 1 OFFSET $offset");
...
$mysqli->commit();

【讨论】:

  • 哇,这是高级 SQL。这在 PHP 上可行吗?以及我需要在 mysqli_query() 上编写的完整代码?
  • 也许该脚本使用mysqli::prepare会很有用
  • @Lumbendil:我确实支持在适当的情况下使用参数。在上面的例子中,SQL 注入的风险是最小的。我们知道该值来自rand(),并且该函数只返回整数。
  • 但是,如果要检索多行,则可以多次执行查询,而无需在多个场合进行分析。
  • @thekosmix,您不需要执行该子查询,因为无论如何,WHERE 条件将在应用 ORDER BY 之前限制行数。
【解决方案2】:
select ID, NAME, CLASS
from YOURTABLE
where CLASS='one'
order by rand()
limit $x

rand() 订购不是特别有效,但它是最小/最快的方式。

【讨论】:

  • 注意:我使用大表,并且 ORDER BY RAND() 对表中的所有行进行排序,并且速度非常慢。
  • 是的,但它只会对类为“一”的行进行排序,而不是对整个表进行排序。
  • 类“one”可以包含数千行。顺便问一下,我可以得到你的 Messenger 和 Skype 吗?
【解决方案3】:
SELECT * FROM `table` WHERE `class`="one" ORDER BY RAND() LIMIT 5

【讨论】:

  • 注意:我使用大表,并且 ORDER BY RAND() 对表中的所有行进行排序,并且速度非常慢。
猜你喜欢
  • 1970-01-01
  • 2019-01-25
  • 2010-11-19
  • 2011-04-16
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多