如何在严格模式下正确使用分组方式?

问题描述 投票:1回答:2

我有这样的消息表:

CREATE TABLE `message` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `from_id` bigint(20) unsigned NOT NULL,
    `to_id` bigint(20) unsigned NOT NULL,
    `body` text COLLATE utf8mb4_unicode_ci NOT NULL,
    `status` tinyint(4) NOT NULL,
    `created_at` timestamp NULL DEFAULT NULL,  
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

并尝试选择每一个最后一个从userX到userY的消息,但是mysql总是说我有未聚合的列(没有only_full_group_by工作正常)。如何在严格模式下选择此项?无效的查询,例如:

select
     t1.created_at,
     t1.from_id,
     t1.to_id,
     t1.body,
     t1.status,
     ( select created_at from test1.message where from_id = t1.from_id order by created_at desc limit 1 ) as last_timestamp

from test1.message as t1
group by t1.from_id 
having t1.created_at = last_timestamp
mysql sql group-by greatest-n-per-group having-clause
2个回答
0
投票

不聚合-而是过滤。

一个选项使用相关子查询,该子查询计算每个用户的最大created_at

 select m.*
 from message m
 where m.created_at = (
      select max(m1.created_at) from message m1 where m1.from_id = m.from_id
)

您还可以使用反left join模式:

select m.*
from message m
left join message m1 on m1.from_id = m.from_id and m1.createt_at > m.created_at
where m1.id is null

此短语为:获取没有其他记录的记录,这些记录具有相同的from_id和更大的created_at


0
投票

您甚至不需要在这里使用GROUP BY,没有它,您当前的查询实际上应该是有效的:

SELECT
    t1.created_at,
    t1.from_id,
    t1.to_id,
    t1.body,
    t1.status,
    (SELECT t2.created_at FROM test1.message t2
     WHERE t2.from_id = t1.from_id
     ORDER BY t2.created_at DESC LIMIT 1) AS last_timestamp
FROM test1.message AS t1
HAVING t1.created_at = last_timestamp;

MySQL重载了HAVING运算符,使其可以代替WHERE子句使用,其附加功能是实际上可以在其中使用在SELECT子句中定义的别名。

© www.soinside.com 2019 - 2024. All rights reserved.