我有一张下表,只想选择所有用户的最后两个条目。
来源表:
-------------------------------------
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
任何想法都要产生这个输出。
答案 0 :(得分:1)
使用MySQL user defined
变量可以实现此目的:
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
注意:如果您希望每个用户最多有x
个条目,请更改where子句中的条件,如下所示:
WHERE t.row_number <= x
<强>解释强>
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;
此查询按userId
的升序和quizendtime(AID)
的降序对所有数据进行排序。
现在对这个(多个)排序数据进行分析。
每当您看到新的userId
分配row_number (1)
时。如果您再次看到同一个用户,则只需增加row_number
。
最后只过滤那些拥有row_number <= 2
的记录,确保每个用户最多有两个最新条目。
编辑:正如Gordon指出的那样,mysql
中使用用户定义变量的表达式的评估不能保证始终遵循相同的顺序,因此上述查询会稍加修改:
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;
答案 1 :(得分: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;