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


Select unique pairs of users from a table at random

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

我有如下的用户表:

表: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中完成吗?

这确实是前一个问题的重复,所以答案在那里。

然而,即使在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']};
}

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

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

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;

一步一步,这将:

  • 将用户列表按随机顺序排序
  • 为其分配行号(否则该顺序将没有意义)
  • 将相同的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;