我有这张桌子,
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分),请告诉:)
非常感谢您的帮助,欢迎所有帮助:)
答案 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中搞乱它。