2015-11-01 15 views
1

我的目标是从每个帐户的表格中获取最后几行(我正在尝试三行)。我没有问题得到第一排,但我无法制作前三排最近的排。举例来说,假设我有如下表:如何抓取MySQL中的最后三行

+--------+------------+------------+-----------+ 
| 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,他们都产生相同的结果

+0

为什么会出现子选择查询?它的目的是什么? –

+0

哪个子查询?如果您指的是'from'内的那个,那么每个帐户的行数可以限制为3个。连接内的子查询用于初始化变量。 – Jujunol

+1

您的查询实际上给出了您列出的结果 - 问题是什么? – amdixon

回答

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。无法预测您是否会获得Item1,3和4或2,3和4.但是,您永远不应该获得Item1,2和3.

另请注意,rownum不是1到7,而是分别递增每个帐户。这是对的。对于相同的查询,您的输出不同。我想我知道发生了什么事。

你很聪明的子查询依赖于子选择中列的操作顺序。特别是这个。

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

这就是为每个帐户分配一组单独的rownums的技巧。它依靠这样的事实,即行按帐户排序,@rownum@account之前设置。

问题是,我不认为你可以依靠那个。

+0

这个输出与他需要的不同#Item1'不应该在那里而是'item2'应该在那里..对吗? –

+0

对,我忽略了Item1和2在测试数据中有相同的日期。当项目2日期切换到* -02在SQLFiddle提供之前我甚至注意到了,结果工作意味着它与我的服务器做我猜:/ – Jujunol

+0

@Jujunol我怀疑问题是作战中选择列的顺序是不可靠的。我不完全确定。 – Schwern

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:[email protected]+1, ...; 

但是,评价涉及用户 变量表达式的顺序是不确定的。

相关问题