我的MySQL数据库中有以下表格:
Table temperature
id - sensor_id - value - created_at
1 1 4.5 04-11-2014
2 1 2.2 05-11-2014
3 1 3.3 06-11-2014
4 2 4.5 04-11-2014
5 2 2.2 05-11-2014
6 2 3.3 06-11-2014
我要做的是为每个sensor_id获取最新的N行。
我设法找到了许多不同的解决方案,但其中大多数都包含非常低效的连接,在我的情况下是不够的,因为我有100万行+并且查询非常慢。
最接近有效查询的是:
set @num := 0, @sensor_id:= '';
select id, sensor_id, value, created_at,
@num := if(@sensor_id = sensor_id, @num + 1, 1) as row_number,
@sensor_id := sensor_id as dummy
from temperature
group by id, sensor_id, value, created_at
having row_number <= 2;
此查询来自本文http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/,但问题是它需要FIRST N,而不是LATEST N行。如何引入ORDER BY,以获取最新的,而不是前N行?
如果查询最新的2行,则所需的结果应如下所示:
id - sensor_id - value - created_at
2 1 2.2 05-11-2014
3 1 3.3 06-11-2014
5 2 2.2 05-11-2014
6 2 3.3 06-11-2014
答案 0 :(得分:2)
您可以订购结果,然后应用row_number逻辑
set @num := 0, @sensor_id:= '';
select *,
@num := if(@sensor_id = sensor_id, @num + 1, 1) as row_number,
@sensor_id := sensor_id as dummy
from
(select id, sensor_id, value, created_at
from temperature
order by sensor_id, created_at desc) T
group by id, sensor_id, value, created_at
having row_number <= 2;
答案 1 :(得分:0)
select id, sensor_id, value, created_at,
@num := if(@sensor_id = sensor_id, @num + 1, 1) as row_number,
@sensor_id := sensor_id as dummy
from my_table, (select @num := 0, @sensor_id:= '') vars
group by id DESC, sensor_id, value, created_at
having row_number <= 2;
答案 2 :(得分:0)
如果由于行数导致连接效率低,那么使用用户变量也可能效率低,因为查询需要检查每一行。
如果您在返回结果后稍微处理结果以获得您想要的格式,那么还有另一种选择。
SELECT sensor_id, SUBSTRING_INDEX(GROUP_CONCAT(CONCAT_WS(':', id, sensor_id, value, created_at) ORDER BY created_at DESC SEPARATOR '#'). '#', 4)
FROM temperature
GROUP BY sensor_id
这是使用CONCAT_WS将行中的所有值一起滚动,用“:”分隔。然后,它使用GROUP_CONCAT将所有这些值连接在一起,用于单个传感器ID,以#降序排列日期顺序(假设日期是实际日期格式,而不是文本dd-mm-yyyy格式)。最后,SUBSTRING_INDEX用于仅获取最后N行数据(在本例中我刚刚使用了4行)。如果您访问的数据包含任何“:”或“#”字符,则可以轻松使用其他分隔符。
返回此内容后,您需要将每个返回的行拆分回其各自的字段。
请注意,GROUP_CONCAT结果的最大长度(我认为)默认为1024个字符。这可以更改,但根据数据量和所需的行数可能不是问题。