我的目标是从每个帐户的表中获取最后几行(我正在尝试三行)。我可以毫不费力地获得第一行,但是我在制作前三行时遇到了麻烦。例如,假设我有下表:
+--------+------------+------------+-----------+
| 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 :(得分: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;
中对此进行了解释
作为一般规则,除了在SET语句中,你永远不应该 为用户变量赋值并读取其中的值 声明。 。 。在下面的语句中,您可能会认为MySQL 将首先评估@a然后再做第二个任务:
SELECT @a, @a:=@a+1, ...;
但是,涉及用户的表达式的评估顺序 变量未定义。
答案 1 :(得分:1)
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
。
问题是,我认为你不能依赖它。