有一个表消息,其中包含如下所示的数据:
Id Name Other_Columns
-------------------------
1 A A_data_1
2 A A_data_2
3 A A_data_3
4 B B_data_1
5 B B_data_2
6 C C_data_1
如果我按名称从消息组中运行查询select *,我将得到如下结果:
1 A A_data_1
4 B B_data_1
6 C C_data_1
哪个查询将返回以下结果?
3 A A_data_3
5 B B_data_2
6 C C_data_1
也就是说,应该返回每个组中的最后一条记录。
目前,这是我使用的查询:
SELECT
*
FROM (SELECT
*
FROM messages
ORDER BY id DESC) AS x
GROUP BY name
但这看起来效率很低。还有其他方法可以达到同样的效果吗?
如果需要每个Name的最后一行,那么可以按Name为每个行组提供行号,并按Id降序排序。
查询
SELECT t1.Id,
t1.Name,
t1.Other_Columns
FROM
(
SELECT Id,
Name,
Other_Columns,
(
CASE Name WHEN @curA
THEN @curRow := @curRow + 1
ELSE @curRow := 1 AND @curA := Name END
) + 1 AS rn
FROM messages t,
(SELECT @curRow := 0, @curA := '') r
ORDER BY Name,Id DESC
)t1
WHERE t1.rn = 1
ORDER BY t1.Id;
SQL小提琴
使用子查询返回正确的分组,因为您已经完成了一半。
试试这个:
select
a.*
from
messages a
inner join
(select name, max(id) as maxid from messages group by name) as b on
a.id = b.maxid
如果它不是id,你想要的最大值:
select
a.*
from
messages a
inner join
(select name, max(other_col) as other_col
from messages group by name) as b on
a.name = b.name
and a.other_col = b.other_col
通过这种方式,可以避免在子查询中进行相关子查询和/或排序,这往往非常缓慢/低效。