MySQL使用WHERE子句平均分配随机行

时间:2013-05-22 10:46:28

标签: mysql sql database

我有这张桌子,

person_id   int(10) pk
points      int(6) index
other columns not very important

我有这个随机函数,在具有10M行的表格上非常快:

SELECT person_id
  FROM persons AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(person_id)
                        FROM persons)) AS id)
        AS r2
 WHERE r1.person_id >= r2.id
 ORDER BY r1.person_id ASC
 LIMIT 1

这一切都很棒,但现在我希望只展示有分数的人> 0.示例表:

PERSON_ID      POINTS
1              4
2              6
3              0
4              3

当我将AND points > 0附加到where子句时,无法选择person_id 3,因此会创建间隙,并且当随机选择person_id 3时,将选择person_id 4。这给了人4更大的选择机会。任何人都有建议我如何调整查询以使其与where子句一起使用,并为所有行提供相同的选择机会百分比。

信息表:表格统一,person_id中没有空白。大约90%将获得0分。我想查询points = 0和points>的位置。 0

之前有人会说,请使用rand():对于行数超过100k的表格,这不是解决方案。

加分问题:是否可以在1个查询中选择x个随机行,所以当我想要更多随机行时,我不必多次调用此查询?

重要说明:性能是关键,查询可能不会比目前的查询花费更长的时间,查询可能不会花费0.0005秒,我宁愿保持在0.05秒以下。

最后一点:如果您认为查询永远不会满足上述要求,但可以采用其他解决方案(例如获取100行并显示x随机且超过0分),请告诉:)

非常感谢您的帮助,欢迎所有帮助:)

1 个答案:

答案 0 :(得分:1)

您可以为您真正想要使用的记录生成内联无间隙ID,然后使用可用记录总数生成随机选择器。

试试这个(为row_number生成器选择答案here的道具):

    SELECT r1.*
    FROM
        (SELECT  person_id,
                 @curRow := @curRow + 1 AS row_number
        FROM persons as p,
             (SELECT @curRow := 0) r0
        WHERE points>0) r1
    , (SELECT COUNT(1) * RAND() id
       FROM persons
       WHERE points>0) r2
    WHERE r1.person_id>=r2.id
    ORDER BY r1.person_id ASC
    LIMIT 1;

你可以在this sqlfiddle中搞乱它。