在我的数据库表格中,我有5列id, l_num, s_num, win, claimed
。有415,000条记录。如何随机选择20,000条记录并使用1
字段中的win
更新记录?
我知道我可以使用SELECT * FROM tableName ORDER BY RAND() LIMIT 20000
来选择那些随机记录,但我也读过这种类型的选择对于大量数据来说效率低下。
我只需要在数据库上执行一次。一旦所有记录都被标记,我们就可以一次只检查一个标记。
答案 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更精确的解决方案。