我有这样的消息表:
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
不聚合-而是过滤。
一个选项使用相关子查询,该子查询计算每个用户的最大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
。
您甚至不需要在这里使用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
子句中定义的别名。