2012-12-09 105 views
1

我想要一个PHP代码来逐个绘制一些ID,而不需要从MySQL数据库中的表中随机替换。没有替换的随机抽取

现在我实现它是这样的:

有一个叫箱

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;" 

的问题是:

如果表中的“盒子”中包含2000条记录,我有绘制了1000多个ID,下一个绘图的SQL将会很长。 我想知道更长的SQL语句会使MySQL中的程序或进程运行速度变慢吗?如果是的话,是否有解决此问题的解决方案/设计/算法表中的记录可能会增加,因此我无法在绘图前在ID上制作随机序列。


更多关于这个问题:

的PHP代码将被多个用户调用,因此每个用户都有已被支取/她一些不同的ID。

实际上,在我目前的设计中,用户绘制的ID存储在PHP会话变量中。当用户想要绘制时,存储在会话变量中的ID将会像上面那样访问绘图SQL。

回答

1

所写的大部分查询将与您的查询大致相同。

顺便说在您的查询条件相当于NOT IN,它可能更容易为你一个NOT IN

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

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

为什么它不会慢下来的一篇文章是here(记住您的查询相当于一个没有)

1

为什么不在表中添加另一列来指示是否绘制了该数字?

然后将查询简单地变为:

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

,然后算账:你画

UPDATE box SET drawn = 1 WHERE id = 43或任何ID。

+0

这是因为多个用户将使用该代码来绘制id。 实际上,已绘制的ID保存在会话中。 – Timespace7

+0

我不确定我是否理解......为什么有多少用户正在绘制数字?你是说每个用户每个号码可以绘制一次吗?在这种情况下,创建一个附加表格将用户映射到已为该用户绘制的数字 –

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; 
+0

这是另一种类似于我当前的解决方案。您的设计将ID存储在数据库中,而不是将其存储在会话变量中。但是,你的设计会让这张桌子有很多记录。 我期待一个优雅的结构设计来解决这个问题!>< – Timespace7

+0

表可以有成千上万的记录。你在用光谱48k做什么工作? – Popnoodles

+0

我知道表格可以有成千上万的记录。但是太多记录会使程序运行速度非常缓慢? – Timespace7

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 boxid 
from userbox 
where userboxid > <last user box id> and userid = <userid> 
limit 1 

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

+0

好的设计!但不幸的是,框中的记录有时会增加。 – Timespace7

+0

框中的更改是否会影响当前正在访问该框的用户或仅重新启动的新用户? –