【问题标题】:Select unique pairs of users from a table at random从表中随机选择唯一的用户对
【发布时间】:2017-01-26 17:45:32
【问题描述】:

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

我有以下用户表:

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

【问题讨论】:

  • 既然你用php标记了它:在php中做。它在mysql中效率低下。使用您的数字 1...max 生成一个数组,例如使用shuffle 并使用该数组填充配对表(数组中的第一个值是第一个 from_id,第二个值是第一个 to_id,第三个值是第二个 from_id 等等)。
  • 感谢@Solarflare 的评论,但我希望随机用户配对数据库中的记录。随机配对很容易在 php 中设置,但我想从数据库中选择查询。

标签: php mysql sql database codeigniter


【解决方案1】:

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

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 = 1 和rownum = 2 得到值pairnum = 0,接下来的两行将得到pairnum = 1 等等)
  • 这些配对行的第一行将获得值from_id = user_id 和to_id = null,另一行将获得to_id = user_id 和from_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;

【讨论】:

    【解决方案2】:

    这确实是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']};
    }
    

    如果您想允许列出不匹配的用户,只需将第二个 fetch 移到循环内部即可。然后在那里处理可能丢失的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-09
      • 2012-03-27
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多