如何在mysql中获取X个唯一记录

如何在mysql中获取X个唯一记录,mysql,sql,Mysql,Sql,我想从一个最多有2条相同用户记录的表中获取10条记录 mysql表包含来自用户的消息。我想获得唯一的用户消息,这很容易,如果我只想要一条唯一的消息,我可以使用distinct来获得它。但是我想要两条独特的用户信息 下表显示了原始数据 -------------------------------------------------------------- | id | user_id | message | ------

我想从一个最多有2条相同用户记录的表中获取10条记录

mysql表包含来自用户的消息。我想获得唯一的用户消息,这很容易,如果我只想要一条唯一的消息,我可以使用distinct来获得它。但是我想要两条独特的用户信息

下表显示了原始数据

--------------------------------------------------------------
| id | user_id | message                                     | 
--------------------------------------------------------------
| 1  | 111     | this is message A from user 1               |
--------------------------------------------------------------
| 2  | 111     | this is message B from user 1               |
--------------------------------------------------------------
| 3  | 111     | this is message C from user 1               |
--------------------------------------------------------------
| 4  | 222     | this is message A from user 2               |
--------------------------------------------------------------
| 5  | 222     | this is message B from user 2               |
--------------------------------------------------------------
| 6  | 222     | this is message C from user 2               |
--------------------------------------------------------------
| 7  | 333     | this is message A from user 3               |
--------------------------------------------------------------
| 8  | 333     | this is message B from user 3               |
--------------------------------------------------------------
| 9  | 333     | this is message C from user 3               |
--------------------------------------------------------------
... so on ...
现在我需要一个查询,它可以为每个用户带来2个结果,如下所示,最多10条记录:

--------------------------------------------------------------
| id | user_id | message                                     | 
--------------------------------------------------------------
| 1  | 111     | this is message A from user 1               |
--------------------------------------------------------------
| 2  | 111     | this is message B from user 1               |
--------------------------------------------------------------
| 4  | 222     | this is message A from user 2               |
--------------------------------------------------------------
| 5  | 222     | this is message B from user 2               |
--------------------------------------------------------------
| 7  | 333     | this is message A from user 3               |
--------------------------------------------------------------
| 8  | 333     | this is message B from user 3               |
--------------------------------------------------------------
... so on ...
编辑:

使用类似这样的查询来获取按用户id分组的记录只能带来单个记录:

select max(id) as id, user_id, max(message) as message from user_messages group by user_id
但我无法找到一种方法为每个用户获取两组记录

编辑2:

使用编程语言解决方案,我们可以这样做:

- we need 10 records total
- we need 2 records max per user
- we can run a loop => 10 / 2 = 5 times
- each time we get a distinct user record
- each next time we append `id not in` to the query to avoid already loaded records
比如:

$data = [];
$ids = [0]; // keep a value in it so that first query does not give error
for ($i=0; $i<5; $i++) {
  $res = mysql_query("select max(id) as id, user_id from user_messages where id not in (".implode(',', $ids).") group by user_id");
  while ( ($row = mysql_fetch_assoc($res)) ) {
    $ids[] = $row['id'];
    $data[] = $row;
  }
}

但这不是最好的解决方案,因为它涉及代码,而不是纯sql。

在MySQL 8+中,您将使用行号:

在早期版本中,可以使用相关子查询:

select um.*
from user_messages um
where um.id <= any (select um2.id
                    from user_messages um2
                    where um2.user_id = um.user_id
                    order by um2.id
                    limit 2
                   );

顺便说一下,any可以处理一个用户少于两条消息的情况。

实际上,我想不出任何解决方案。我知道如果我想要一个单独的用户记录,我可以得到它,但是对于多个不同的记录,我不知道如何做,甚至不知道是否可以通过查询来实现。这就是我发布这个问题的原因。然后发布到目前为止您尝试过的查询,您得到的当前结果是什么,您研究了什么?是否有任何列建议对行进行排序?时间戳?是否要每个用户的最新行?前两个?选择返回哪两行的标准是什么?没有标准,可以选择任意两行。如果重要的话,我们可以按id字段进行排序,但这不是一个要求。我在想,如果您添加另一列,获得每个组的计数和每个组的2,那么它将对您有效。
select um.*
from (select um.*,
             row_number() over (partition by user_id order by id) as seqnum
      from user_messages um
     ) um
where seqnum <= 2;
select um.*
from user_messages um
where um.id <= any (select um2.id
                    from user_messages um2
                    where um2.user_id = um.user_id
                    order by um2.id
                    limit 2
                   );