而不是MySQL ORDER BY RAND

时间:2018-02-22 19:17:58

标签: mysql sql random sql-order-by

我使用此查询:

SELECT f.id FROM articles f
JOIN ( SELECT RAND() * (SELECT MAX(id) FROM articles) AS max_id ) AS m
WHERE f.id >= m.max_id
ORDER BY f.id ASC
LIMIT 5

问题是它返回了意外的行数。它可以是1行或3行或5行。但我需要5行。

2 个答案:

答案 0 :(得分:2)

您的查询可能存在的问题是它只是随机选择一条记录而其余记录是顺序的。如果你想真正随机选择所有5个,你必须逐个选择它们:

... WHERE validto = 'infinity'

如果ID是连续的,没有间隙,则此方法有效。如果您有间隙,则必须将相等更改为小于,并限制为一条记录:

(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random = f.id) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random = f.id) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random = f.id) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random = f.id) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random = f.id)

然而,就像他在answer中提到的dnswlt一样。经典的解决方案更简单,适用于小型表:

(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random <= f.id LIMIT 1) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random <= f.id LIMIT 1) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random <= f.id LIMIT 1) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random <= f.id LIMIT 1) UNION ALL
(SELECT f.id FROM articles f INNER JOIN (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles) + 1) AS random) m ON m.random <= f.id LIMIT 1)

答案 1 :(得分:1)

您的问题看起来像是MySQL select 10 random rows from 600K rows fast的副本。

根据您在表格中的行数以及您愿意接受的响应时间,您可以先尝试使用经典变体:

SELECT f.id FROM articles f
ORDER BY RAND()
LIMIT 5

如果它不到一百万,这可能就足够了。

否则,您可以应用链接文章中描述的技巧,以及UNION ALL 5个此类查询,大致如下:

(SELECT r1.id
  FROM articles AS r1 JOIN
       (SELECT CEIL(RAND() *
                     (SELECT MAX(id)
                        FROM articles)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1)
 UNION ALL
 (SELECT r1.id
  FROM articles AS r1 JOIN
       (SELECT CEIL(RAND() *
                     (SELECT MAX(id)
                        FROM articles)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1)
 UNION ALL
 ... (three more queries to retrieve 5 rows)

如果您的行数很少,则此解决方案可能会出现重复。但是如果你有几行,你可以使用上面更简单的解决方案:)

我为第二个版本创建了SQL Fiddle。 HTH!