随机抽奖无需更换

时间:2012-12-09 15:05:31

标签: php mysql sql algorithm random

我希望有一个PHP代码可以逐个绘制一些ID,而无需从MySQL数据库中的表中随机替换。

现在我像这样实现它:

有一个名为box的表

CREATE TABLE box
(
id INT UNSIGNED AUTO_INCREMENT,
PRIMARY KEY (id)
);

假设它包含15条记录,

id:
=====
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
=====

已经绘制的ID将被记录并在下一次抽奖中排除。

例如,

一开始,绘图的SQL将是

SELECT id FROM box RAND() LIMIT 1;`.

说结果是4。

然后我画了4,下一个用于绘图的SQL将是

SELECT id FROM box WHERE id != 4 ORDER BY RAND() LIMIT 1;

这次说结果是6。

也就是说,我已经绘制了4和6,因此下一个绘制的SQL将是

SELECT id FROM box WHERE id != 4 AND id != 6 ORDER BY RAND() LIMIT 1;"

问题在于:

如果表'box'包含2000条记录并且我已经绘制了1000多个ID,则下一个绘制的SQL将会很长。 我想知道更长的SQL语句是否会使MySQL中的程序或进程运行得更慢?如果是,是否有解决方案/设计/算法来解决此问题? 表中的记录可能会增加,因此我无法在绘图前对ID进行随机序列。


有关此问题的更多信息:

PHP代码将由多个用户调用,因此每个用户都有一些由他/她绘制的不同ID。

实际上,在我目前的设计中,用户绘制的ID存储在PHP会话变量中。当用户想要绘制时,将访问存储在会话变量中的id,如上所述绘制SQL。

4 个答案:

答案 0 :(得分:1)

为什么不在表格中添加另一列来表明是否已绘制该数字?

然后你的查询就变成了:

SELECT id FROM box WHERE drawn = 0 ORDER BY RAND() LIMIT 1

然后,之后:

UPDATE box SET drawn = 1 WHERE id = 43或您绘制的任何ID。

答案 1 :(得分:1)

编写的大多数查询所用的查询时间大致相同。

顺便提一句,查询中的条件等同于NOT IN,并且您可以更轻松地应用NOT IN

SELECT * FROM box WHERE id NOT IN (a[0],a[1]...)

现在关于增加查询大小是否会减慢MySQL的答案是否定的,不是真的。

关于它为什么不会降低速度的文章是here(请记住,您的查询相当于不在其中)

答案 2 :(得分:1)

如果该框具有固定数量的记录,那么我倾向于采用一种方法为用户提供更多空间,但应该更快地运行。由于order by rand()

,您的方法需要全表扫描才能检索下一个值

相反,为每个用户创建一个单独的“框”,并最初进行随机排序:

CREATE TABLE userbox (
    userboxid INT UNSIGNED AUTO_INCREMENT,
    int boxid,
    userid int,
    PRIMARY KEY (userboxid),
    KEY (userid, userboxid)
);

然后,当用户启动时,插入该用户的框中:

insert into userbox
    select id, <userid>
    from box
    order by rand()

后续检索将使用select语句,例如:

select boxid
from userbox
where userboxid > <last user box id> and userid = <userid>
limit 1

这种方法的优点是,在填充框的开销之后,每次检索下一个id应该只需要查看索引中的下一个值并从数据页中获取框id。

答案 3 :(得分:0)

您可以为每个用户绘制的数字添加另一个表

user_id     id
  1         129
  1         832
  2         23
 ...

然后

SELECT id FROM box WHERE id NOT IN (SELECT id FROM user_drawn WHERE user_id=1) RAND() LIMIT 1;