我想执行单个SELECT
查询,该查询返回每个ID的最新2条记录(按日期排序)。对于每个给定的ID,日期值并不总是唯一的,所以我必须处理它(看看ID = 1,我想只获得2条记录,尽管它有2条记录来自同一天......)
例如,对于此表:
+------+------------+-------+
| 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)
如何显示所需的结果?
答案 0 :(得分:2)
您可以使用变量来跟踪前一记录的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
构造用于评估表达式,然后根据第一个表达式是假还是true来评估其他内容。在这些表达中,有时会进行分配。
答案 1 :(得分:1)
首先,使用SELECT
语句获取ORDER
中的所有行以及每个ID的count
,例如:
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;
完成后,您可以将其包装到另一个select中,并仅获取count&lt; = 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 。