Mysql 从表中选择所有用户的最近n个条目

Mysql 从表中选择所有用户的最近n个条目,mysql,mysql-workbench,Mysql,Mysql Workbench,我有一个下表,只想选择所有用户的最后2个条目 源表: ------------------------------------- UserId | QuizId(AID)|quizendtime(AID)| -------------------------------------- 1 10 2016-5-12 2 10 2016-5-12 1 11 2016-6-12 2

我有一个下表,只想选择所有用户的最后2个条目

源表:

-------------------------------------
UserId | QuizId(AID)|quizendtime(AID)|
--------------------------------------
1         10          2016-5-12
2         10          2016-5-12 
1         11          2016-6-12
2         12          2016-8-12
3         12          2016-8-12
2         13          2016-8-12
1         14          2016-9-12
3         14          2016-9-12
3         11          2016-6-12
预期输出类似,应该只列出所有用户最近的2个quizid条目

-------------------------------------
UserId | QuizId(AID)|quizendtime(AID)|
--------------------------------------
1         14          2016-9-12
1         11          2016-6-12
2         13          2016-8-12
2         12          2016-8-12
3         14          2016-9-12
3         12          2016-8-12
任何想法都可以生成此输出。

使用MySQL用户定义变量,您可以完成以下任务:

SELECT 
t.UserId,
t.`QuizId(AID)`,
t.`quizendtime(AID)`
FROM 
(
    SELECT 
    *,
    IF(@sameUser = UserId, @a := @a + 1 , @a := 1) row_number,
    @sameUser := UserId
    FROM your_table
    CROSS JOIN (SELECT @a := 1, @sameUser := 0) var
    ORDER BY UserId , `quizendtime(AID)` DESC
) AS t
WHERE t.row_number <= 2
此查询按userId的升序和quizendtimeAID的降序对所有数据进行排序

现在在这个多排序的数据上走一走

每次你看到一个新的用户ID时,分配一个1号行。如果您再次看到同一用户,则只需增加行数即可


最后,解决方案的关键是只过滤那些具有行数用户定义变量的记录。但是,将所有变量赋值放在一个表达式中是非常重要的。MySQL不保证select中表达式的求值顺序,事实上,有时会以不同的顺序处理它们

select t.*
from (select t.*,
             (@rn := if(@u = UserId, @rn + 1,
                        if(@u := UserId, 1, 1)
                       )
             ) as rn
       from t cross join
            (select @u := -1, @rn := 0) params
       order by UserId, quizendtime desc
      ) t
where rn <= 2;

这太棒了。。工作完全符合我的期望。。我试图通过创建临时表和简单连接来实现这一输出。。你能建议使用临时表来获得这个输出的逻辑吗?我解决了我的问题,这只是为了我的理解,我可以看到没有交叉连接也会产生相同的结果,如果我删除交叉连接会发生什么?你是如何修改离开交叉连接部分的查询的?任何阅读此答案的人:请参阅下面的我的答案。这不能保证有效,因为变量正在不同的表达式中分配和使用。您好,Gordon,如果您解释一下为什么我们需要在查询中使用交叉连接,这将非常有用。。。没有交叉连接,上面的查询工作正常。@prababuddy。如果删除交叉连接,则查询将失败。您需要某种方式来连接from子句中的两项。除非以其他方式初始化变量。选择不初始化变量似乎有点危险,但如果变量还没有值,也可以。
SELECT 
t.UserId,
t.`QuizId(AID)`,
t.`quizendtime(AID)`
FROM 
(
    SELECT 
    *,
    IF (
            @sameUser = UserId,
            @a := @a + 1,
            IF(@sameUser := UserId, @a := 1, @a:= 1)
        )AS row_number
    FROM your_table
    CROSS JOIN (SELECT @a := 1, @sameUser := 0) var
    ORDER BY UserId , `quizendtime(AID)` DESC
) AS t
WHERE t.row_number <= 2;
select t.*
from (select t.*,
             (@rn := if(@u = UserId, @rn + 1,
                        if(@u := UserId, 1, 1)
                       )
             ) as rn
       from t cross join
            (select @u := -1, @rn := 0) params
       order by UserId, quizendtime desc
      ) t
where rn <= 2;