【问题标题】:MySQL select 3 UNIQUE random ID rows fast WHEREMySQL 快速选择 3 个唯一随机 ID 行 WHERE
【发布时间】:2013-12-16 13:36:27
【问题描述】:

我需要能够从一个随着时间逐渐增长和增长的表中选择 3 个唯一的随机 MySQL ID 行,并且有一个 WHERE 'status' = 'available'。所以它只在 status = available 时选择 id 号。

不会有任何空白,因为所有数据都会保留以符合记录保存要求,如果用户删除了数据,它实际上并没有被删除,只是 STATUS 被标记为“已删除”。

我已经阅读了很多关于该主题的帖子,但这一切似乎都归结为只选择 1 个结果,然后重复 3 次,问题是,它可能会再次选择相同的 ID,所以我的问题的任何解决方案都会不胜感激。

谢谢

:)

我正在考虑做这样的事情 (取自这里...MySQL select 10 random rows from 600K rows fast

SELECT id
  FROM table AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM table)) AS id2)
        AS r2
 WHERE r1.id >= r2.id2 AND status = 'available'
 ORDER BY r1.id ASC
 LIMIT 1

这给了我我需要的东西,但它只返回 1 个随机唯一“选择”,加上如果我将它限制为 3,它并不总是选择 3,如果它确实选择 3,它们似乎总是顺序的,即不是随机的!

有没有办法重复查询,存储选择的 ID 并继续循环/运行查询,直到随机选择不同的 3 个 ID。这是我的问题:)

【问题讨论】:

  • 这可能很快,但它往往会在删除后“更喜欢”记录。

标签: php mysql sql random


【解决方案1】:

你试过了吗:

SELECT *
FROM mytable
WHERE status = 'available'
ORDER BY RAND( )
LIMIT 0,3;

【讨论】:

  • 添加条件即可:WHERE status = 'available'
  • 这是 OP 在我的答案中留下的内容(已删除,我无法理解)“我需要一个快速的答案,抱歉我的帖子没有正确解释,随着时间的推移可能会有 100 的数千行,并不总是 'limit 3' 会返回 3,有时只返回 1 或 2 –"
  • 这会进行全表扫描,所以不是“快”。
【解决方案2】:
SELECT DISTINCT *
FROM table
WHERE status = 'available'
ORDER BY RAND()
LIMIT 3

DISTINCT 子句应防止重复值。 ORDER BY RAND() 将随机组织结果。

【讨论】:

  • 很好,我忘记了不同的,但是这在包含 100 万行以上的表上会很快吗?
  • 好吧,你不会选择一百万行显示在一个页面中,你会创建分页,对吧?如果您正在为统计数据或排名创建查询,您应该处理数据并将其存储在其他地方。这可能需要一些时间,但每天或每小时只能完成一次(仅作为示例)。无论如何,一旦达到数百万行,大多数操作都需要一些时间。
  • 这会进行全表扫描,所以不是“快”。
【解决方案3】:

请参阅以下内容;在它谈论“差距”的地方,你有等价的(状态=已删除)http://mysql.rjweb.org/doc.php/random#case_auto_increment_with_gaps_1_or_more_rows_returned (并在该链接中查看变体)

  • 要求:AUTO_INCREMENT,可能由于 DELETE 等原因存在间隙
  • 缺陷:只有半随机(行被选中的机会不均等),但它确实部分弥补了差距
  • 缺陷:表格的第一行和最后几行不太可能被传递。

这会获得 50 个“连续”的 id(可能有间隙),然后随机提供 10 个。

-- First select is one-time:
SELECT @min := MIN(id),
       @max := MAX(id)
    FROM RandTest;
SELECT a.*
    FROM RandTest a
    JOIN ( SELECT id FROM
            ( SELECT id
                FROM ( SELECT @min + (@max - @min + 1 - 50) *
                         RAND() AS start FROM DUAL ) AS init
                JOIN RandTest y
                WHERE    y.id > init.start
                ORDER BY y.id
                LIMIT 50           -- Inflated to deal with gaps
            ) z ORDER BY RAND()
           LIMIT 10                -- number of rows desired
         ) r ON a.id = r.id;

是的,它很复杂,但是,无论表大小如何,它都很快。

【讨论】:

    猜你喜欢
    • 2011-05-18
    • 2021-07-03
    • 2020-09-23
    • 1970-01-01
    • 2010-09-17
    相关资源
    最近更新 更多