在MySQL数据库中标记大量随机记录 - 仅限一次

时间:2015-03-23 23:26:49

标签: mysql random

在我的数据库表格中,我有5列id, l_num, s_num, win, claimed。有415,000条记录。如何随机选择20,000条记录并使用1字段中的win更新记录?

我知道我可以使用SELECT * FROM tableName ORDER BY RAND() LIMIT 20000来选择那些随机记录,但我也读过这种类型的选择对于大量数据来说效率低下。

我只需要在数据库上执行一次。一旦所有记录都被标记,我们就可以一次只检查一个标记。

2 个答案:

答案 0 :(得分:2)

您可以使用以下查询:

UPDATE tableName SET win = 1 ORDER BY RAND() LIMIT 20000

答案 1 :(得分:0)

每条记录的选择概率为20000/415000 = 0,04819 ....

因此,您可以选择RAND()小于0.049的所有记录。这将选择大约20335条记录,而从这些,您可以运行LIMIT 20000。

SELECT * FROM tableName WHERE RAND() < (20000/415000)*1.05 LIMIT 20000;

上面,我添加了5%的保证金,以“合理地”确定选择足够的记录。

当然,UPDATE查询也可以这样做,即

UPDATE tableName SET ... WHERE RAND() < (20000/415000)*1.05 LIMIT 20000;

实验上,该方法选择少于20000条记录的概率为7%,边际为1.01,0.5%,边际为1.02,低于0.05%,边际为1.03。

这种方法的另一个缺点是选择不是真正随机的,因为最后的记录被选择的概率较低(因为在检查完整的表之前极有可能满足20,000个记录的配额)

要添加“获胜代码”,您可以使用相同的方法(虽然此时更加近似)

... SET win = CASE WHEN RAND() BETWEEN 0 AND .333 THEN 'potting soil' WHEN RAND() BETWEEN .333 AND .666 THEN 'gift certificate' ELSE 'something else' END WHERE RAND() < ...

这里需要仔细调整值,因为在每次调用时都会计算一次RAND()。因此,如果你想在3种可能性之间平均分配,那么工作:

CASE WHEN RAND() BETWEEN 0 AND 0.333   THEN 1
     WHEN RAND() BETWEEN .333 AND .666 THEN 2
     ELSE                                   3
END

因为第一种情况将被选择33%的时间(这是正确的),那么第二种情况将被选择剩余次的33%,即2/9,并且第三个将覆盖其余的(4/9)。要平均分配范围,您需要33%,50%和50%:

mysql> SELECT r, count(*)/1048576.0 FROM (select case when rand() between 0 and 0.333 then 1 when rand() between 0.333 and 0.666 then 2 else 3 end AS r from numbers) AS a GROUP BY r;
+---+--------------------+
| r | count(*)/1048576.0 |
+---+--------------------+
| 1 |             0.3330 |
| 2 |             0.2218 |
| 3 |             0.4452 |
+---+--------------------+
3 rows in set (0.03 sec)

mysql> SELECT r, count(*)/1048576.0 FROM (select case when rand() between 0 and 0.333 then 1 when rand() between 0 and 0.5 then 2 else 3 end AS r from numbers) AS a GROUP BY r;
+---+--------------------+
| r | count(*)/1048576.0 |
+---+--------------------+
| 1 |             0.3324 |
| 2 |             0.3337 |
| 3 |             0.3339 |
+---+--------------------+
3 rows in set (0.03 sec)

请注意,除法只是概率性的 - 你实际上并没有正好 1 / 3,1 / 3和1/3。

另一种可能性是为每条记录分配一个随机整数,具有足够的颗粒度(例如0到415,000,000之间的随机数),索引,以及(a)通过二分找到值K以便人数索引低于K的正好是20,000,(b)根据模数分配奖品(即0到33之间的ndx%100的每个人都获得礼券。如果你需要经常进行这种操作,请指定一个“命运”号码每个参与者都可能是值得的。

如果提取的数量与总数相比较大(就像在这种情况下那样),那么肯定会采用Salman更精确的解决方案。