我有一个MySQL表players
,我试图将所有玩家随机分为n组(n>=2),每组都有一个确定但可变的大小。
示例时间:
将表players
中的10.000行分为3组,其中A组包含5.000名玩家,B组包含3.000名玩家和C组包含2.000名玩家。
另一个例子可能是:
将表players
中的10.000行分为4组,其中A组包含3.000名玩家,B组包含3.0000名玩家,C组包含2.000名玩家和D组包含2.0000名玩家。
现在我的问题是:
我应该在PHP还是MySQL中这样做?(我想MySQL可能会更快)
在MySQL中,有比为每一行生成随机数并按顺序排列行,然后使用OFFSET和LIMIT来选择行更好(更有效)的方法吗?
我认为最有效、最简单的方法是运行以下查询:
SELECT * FROM players
ORDER BY rand()
然后在几个PHP FOR循环中迭代结果(每组一个)。
这样,您将只运行一个查询,并对结果进行一次迭代(无论如何,这实际上是您必须做的事情)。
您可以在MySQL中执行此操作。策略如下。将行随机化并枚举。然后计算每个组的枚举中的中断。
select t.*,
(case when (seqnum - 1) / totalcnt < 0.3 then 'GroupA'
when (seqnum - 1) / totalcnt < 0.6 then 'GroupB'
when (seqnum - 1) / totalcnt < 0.8 then 'GroupC'
else 'GroupD'
end) as WhichGroup
from (select t.*, @rn := @rn + 1 as seqnum, totalcnt
from t cross join
(select @rn := 0, count(*) as totalcnt from t) const
order by rand()
) t;
order by rand()
确实会减慢速度。然而,获取随机样本并不是一个固有的快速过程。
一种更快的方法——创建与您所寻找的略有不同大小的组——是执行以下操作:
select t.*,
(case when rand() < 0.3 then 'GroupA'
when rand() < 0.6 then 'GroupB'
when rand() < 0.8 then 'GroupC'
else 'GroupD'
end) as WhichGroup
from t;