每个ID的最后2条记录(日期)的sql查询
我想要做一个单一的SELECT
查询,该查询返回每个ID的最新2条记录(按日期排序)。对于每个给定的ID,日期值并不总是唯一的,所以我必须处理它(查看ID = 1,我只想得到2条记录,尽管它有来自同一日期的2条记录.. 。)每个ID的最后2条记录(日期)的sql查询
例如,此表:
+------+------------+-------+
| ID | Date | Value |
+------+------------+-------+
| 1 | 2010 | 33 |
| 1 | 2009 | 23 |
| 1 | 2009 | 41 |
| 1 | 2003 | 55 |
| 1 | 2003 | 24 |
| 2 | 2009 | 52 |
| 2 | 2008 | 23 |
| 2 | 2007 | 39 |
| 2 | 2006 | 22 |
|
|
| ... | ... | ... |
+------+------------+-------+
我将有望获得:
+------+------------+-------+
| ID | Date | Value |
+------+------------+-------+
| 1 | 2010 | 33 |
| 1 | 2009 | 23 |
| 2 | 2009 | 52 |
| 2 | 2008 | 23 |
| ... | ... | ... |
+------+------------+-------+
我使用这个脚本:
SELECT ID, Date, Value
FROM MyTable
WHERE Date >= IFNULL((SELECT Date
FROM MyTable AS T2
WHERE T2.ID = MyTable.ID
ORDER BY Date DESC
LIMIT 1 OFFSET 2),
0)
如何显示所需的结果?
您可以使用该变量,它跟踪上一条记录的id
以及相同id
值的分区内的记录编号。
对于工作,你首先要确保你有一个有序的结果集,然后分配这两个变量的值作为记录的顺序被处理:
select id, date, value
from (
select *
from mytable
order by id, date desc
) ordered,
(select @rn := -1, @id := -1) init
where if(@rn := if(@id = id, @rn + 1, if(@id := id, 1, 1)), @rn, @rn) < 3;
的if
结构用于评估一个表达式,然后根据第一个表达式是否被认为是false或true来评估其他东西。在这些表达式中有时会做出任务。
感谢您的快速回复!但我可以在不使用变量的情况下解决这个问题吗?我可以找到更简单的解决方案吗? –
不可能,因为你的表没有唯一的id列。如果可能的话,那么这将是可能的,但是查询会比这个慢几倍。 – trincot
我明白了,非常感谢你的回答! –
首先,使用SELECT
语句来获得ORDER
所有行与count
沿着每个ID,例如:
SELECT id, `date`, `value`,
@count := IF(@previous = id, @count + 1, 1) AS `count`, @previous := id
FROM test, (SELECT @previous := 0, @count := 1) a
ORDER BY id ASC, `date` DESC;
一旦这样做,你可以把它包装成另一种选择,让只数的那些行< = 2,例如:
SELECT *
FROM (
SELECT id, `date`, `value`,
@count := IF(@previous = id, @count + 1, 1) AS `count`, @previous := id
FROM test, (SELECT @previous := 0, @count := 1) a
ORDER BY id ASC, `date` DESC
) b
WHERE b.count <= 2;
这里的SQL Fiddle。
感谢您的快速回复!但我可以在不使用变量的情况下解决这个问题吗?我可以找到更简单的解决方案吗? –
一个简单的答案是否定的。你在这里试图做的是为每个组应用“限制”,这是MySQL不支持开箱即用的。 –
现在很清楚,非常感谢! –
感谢您的快速响应! 但我可以解决这个问题,而不使用变量? 我可以找到更简单的解决方案吗? –