有一个表消息,其中包含如下所示的数据:

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

但这看起来效率很低。还有其他方法可以达到同样的效果吗?


当前回答

下面是另一种获取最后一条相关记录的方法,使用GROUP_CONCAT和SUBSTRING_INDEX从列表中选择一条记录

SELECT 
  `Id`,
  `Name`,
  SUBSTRING_INDEX(
    GROUP_CONCAT(
      `Other_Columns` 
      ORDER BY `Id` DESC 
      SEPARATOR '||'
    ),
    '||',
    1
  ) Other_Columns 
FROM
  messages 
GROUP BY `Name` 

上面的查询将组所有Other_Columns在同一名称组和使用ORDER BY id DESC将连接所有Other_Columns在一个特定的组降序与提供的分隔符在我的情况下,我已经使用||,使用SUBSTRING_INDEX在这个列表将选择第一个

小提琴演示

其他回答

以下是我的解决方案:

SELECT 
  DISTINCT NAME,
  MAX(MESSAGES) OVER(PARTITION BY NAME) MESSAGES 
FROM MESSAGE;

是什么:

select *, max(id) from messages group by name 

我已经在sqlite上测试了它,它返回所有列和所有名称的最大id值。

下面是一个更有效的版本,只需一行,只要表有时间戳列即可。

SELECT Id, Name, SUBSTRING_INDEX(MAX(CONCAT(TimeStamp, ',', Other_Columns)), ',', -1)
FROM Messages
ORDER BY id DESC GROUP BY Name 

这将返回“Other_Columns”上组的最新记录

我还没有测试大DB,但我认为这可能比连接表更快:

SELECT *, Max(Id) FROM messages GROUP BY Name

另一种方法:

找到每个程序中最大m2_price的属性(一个程序中有n个属性):

select * from properties p
join (
    select max(m2_price) as max_price 
    from properties 
    group by program_id
) p2 on (p.program_id = p2.program_id)
having p.m2_price = max_price