如何抓取MySQL中的最后三行

时间:2015-11-01 06:04:21

标签: mysql sql

我的目标是从每个帐户的表中获取最后几行(我正在尝试三行)。我可以毫不费力地获得第一行,但是我在制作前三行时遇到了麻烦。例如,假设我有下表:

+--------+------------+------------+-----------+
| rownum | entryDate  | particular | accountID |
+--------+------------+------------+-----------+
|      1 | 2015-10-01 | Item1      |         1 |
|      2 | 2015-10-01 | Item2      |         1 |
|      3 | 2015-10-02 | Item3      |         1 |
|      4 | 2015-10-02 | Item4      |         1 |
|      5 | 2015-10-02 | Item5      |         2 |
|      6 | 2015-10-03 | Item6      |         2 |
|      7 | 2015-10-05 | Item7      |         3 |
+--------+------------+------------+-----------+

我想要的是:

+--------+------------+------------+-----------+
| rownum | entryDate  | particular | accountID |
+--------+------------+------------+-----------+
|      4 | 2015-10-02 | Item4      |         1 |
|      3 | 2015-10-02 | Item3      |         1 |
|      2 | 2015-10-01 | Item2      |         1 |
|      6 | 2015-10-03 | Item6      |         2 |
|      5 | 2015-10-02 | Item5      |         2 |
|      7 | 2015-10-05 | Item7      |         3 |
+--------+------------+------------+-----------+

删除了Item1,因为它之前已经有3个。 我尝试了以下代码,但它没有检索最新

select rownum, entryDate, particular, accountID
from (
    select entryDate, particular, accountID
    @rownum := if(@account = accountID, @rownum + 1, 1) rownum,
    @account := accountID 
    from entries 
    join ( select @rownum := 0, @account := 0 ) init
    order by accountID, entryDate desc) t
where t.rownum <= 3 -- Limits the rows per account

如果有人能指出我正确的方向,那就太棒了!

修改 但是,我正在检索的结果是:

+--------+------------+------------+-----------+
| rownum | entryDate  | particular | accountID |
+--------+------------+------------+-----------+
|      3 | 2015-10-02 | Item3      |         1 |
|      2 | 2015-10-01 | Item2      |         1 |
|      1 | 2015-10-01 | Item1      |         1 |
|      6 | 2015-10-03 | Item6      |         2 |
|      5 | 2015-10-02 | Item5      |         2 |
|      7 | 2015-10-05 | Item7      |         3 |
+--------+------------+------------+-----------+

另外,如果它有帮助,我在MySQL工作台,SQLbuddy,PHP(Web应用程序)和PHPMyAdmin上测试了它们,它们都产生相同的结果

2 个答案:

答案 0 :(得分:2)

编写此查询的安全方法是:

select rownum, entryDate, particular, accountID
from (select entryDate, particular, accountID,
             (@rownum := if(@account = accountID, @rownum + 1, 
                            if(@account := accountID, 1, 1)
                           )
             ) as rownum,
      from entries cross join
           (select @rownum := 0, @account := 0 ) init
      order by accountid, entryDate desc
     ) t
where t.rownum <= 3;

documentation

中对此进行了解释
  

作为一般规则,除了在SET语句中,你永远不应该   为用户变量赋值并读取其中的值   声明。 。 。在下面的语句中,您可能会认为MySQL   将首先评估@a然后再做第二个任务:

SELECT @a, @a:=@a+1, ...;
     

但是,涉及用户的表达式的评估顺序   变量未定义。

答案 1 :(得分:1)

如果我修复了语法错误,请

Your query works for me

select rownum, entryDate, particular, accountID
from (
    select entryDate, particular, accountID,
    @rownum := if(@account = accountID, @rownum + 1, 1) rownum,
    @account := accountID 
    from entries 
    join ( select @rownum := 0, @account := 0 ) init
    ORDER BY accountid, entryDate desc
) t
where t.rownum <= 3;

rownum  entryDate            particular         accountID
1       October, 02 2015     Item3              1
2       October, 02 2015     Item4              1
3       October, 01 2015     Item1              1
1       October, 03 2015     Item6              2
2       October, 02 2015     Item5              2
1       October, 05 2015     Item7              3

请注意,Item1和Item2具有相同的entryDate。您是否可以获得第1,3和4或第2,3和4项是不可预测的。但是,您永远不应该获得第1项,第2项和第3项。

另请注意,rownum不是1到7,而是针对每个帐户单独递增。这是对的。您的输出因同一查询而异。我想我知道发生了什么。

您非常聪明的子查询依赖于子选择中列的操作顺序。特别是,这个。

    @rownum := if(@account = accountID, @rownum + 1, 1) rownum,
    @account := accountID

这是为每个帐户分配一组单独的rownums的技巧。它依赖于以下事实:行按帐户排序,并且在@rownum之前设置了@account

问题是,我认为你不能依赖它。