1

我想要一个 PHP 代码从 MySQL 数据库中的表中一个一个地绘制一些 id 而无需随机替换。

现在我像这样实现它:

有一张桌子叫盒子

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

4 回答 4

1

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

然后你的查询就变成了:

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

然后,之后:

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

于 2012-12-09T15:10:11.613 回答
1

编写的大多数查询将花费与您的查询大致相同的时间。

顺便说一下,查询中的条件等同于 NOT IN,您可能更容易应用 NOT IN

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

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

一篇关于为什么它不会减慢速度的文章在这里(记住你的查询相当于一个 not in)

于 2012-12-09T15:11:19.020 回答
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。

于 2012-12-09T15:42:45.810 回答
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;
于 2012-12-09T15:38:22.050 回答