随机选择表中的唯一用户对

时间:2016-09-19 06:06:13

标签: php mysql sql database codeigniter

我想在数据库用户之间创建随机用户对。

我有以下用户表:

表:tbl_users

user_id | name
--------+--------------
1       | Jay
2       | Ram
3       | John
4       | Kevin
5       | Jenny
6       | Tony

我想生成一个像这样的随机结果:

from_id | to_id
--------+---------
1       | 6 
5       | 3 
2       | 4 

这只能在MySQL中完成吗?

2 个答案:

答案 0 :(得分:0)

这确实是a previous question的副本,所以答案就在那里。

然而,即使在MySQL中确实有可能这样做,也没有真正推荐。 PHP是一个更好的处理这个的工具,因为你正在做的是按照某些业务规则实际操作数据。通过在PHP中进行维护会更容易维护,我怀疑它也会减少资源密集度。

一种可行的方法,我更喜欢这样做。是在SQL中进行随机排序,然后将两行和两行相互配对。像这样:

$grouping = {};
// Fetching both rows to ensure that we actually have an even number paired up.
while ($row = $res->fetch_array () && $row2 = $res->fetch_array ()) {
    $grouping[] = {$row['name'], $row2['name']};
}

如果要允许列出不匹配的用户,只需将第二次提取移动到循环内部即可。然后处理可能缺少的结果。

答案 1 :(得分:0)

您可以使用以下代码生成列表:

select max(from_id) as from_id,
       max(to_id) as to_id
from (
  select 
    case when rownum mod 2 = 1 then user_id else null end as from_id,
    case when rownum mod 2 = 0 then user_id else null end as to_id,
    (rownum - 1) div 2 as pairnum
  from (
    select user_id, @rownum := @rownum + 1 as rownum
    from 
      (select @rownum := 0) as init,
      (select user_id from tbl_user order by rand()) as randlist
  ) as randlistrownum
) as randlistpairs  
group by pairnum;

一步一步,这将:

  • 以随机顺序订购用户列表
  • 为其分配一个rownumber(否则订单没有任何意义)
  • 分配两个连续的行pairnum rownum = 1rownum = 2获取值pairnum = 0,接下来的两行将获得pairnum = 1,依此类推)
  • 这些配对行的第一行将获得值from_id = user_idto_id = null,另一行将为to_id = user_idfrom_id = null
  • group by这些成对将它们组合成一行
  • 如果您的用户数量奇数,则一位用户最终会获得to_id = null,因为它没有合作伙伴

如果你更喜欢更短的代码,那就更紧凑了:

select max(case when rownum mod 2 = 1 then user_id else null end) as from_id,
       max(case when rownum mod 2 = 0 then user_id else null end) as to_id
from (
  select user_id, @rownum := @rownum + 1 as rownum, (@rownum - 1) div 2 as pairnum
  from 
     (select @rownum := 0) as init,
     (select user_id from tbl_user order by rand()) as randlist
) as randlistpairs
group by pairnum;