mysql选择组中的最新时间戳
Posted
技术标签:
【中文标题】mysql选择组中的最新时间戳【英文标题】:mysql select latest timestamp in a group 【发布时间】:2014-01-16 21:57:54 【问题描述】:我有一个表,我想为该表选择一个类别中的最新时间戳,该类别由表中特定列的值定义。
具体来说
SELECT *
FROM takelist
WHERE producer_name = 'sean'
AND bucket_id = '2CCEx15_1o'
结果
+-------------+---------------+------------+---------------------+
| takelist_id | producer_name | bucket_id | ts |
+-------------+---------------+------------+---------------------+
| 1 | sean | 2CCEx15_1o | 2013-10-07 18:29:00 |
| 4 | sean | 2CCEx15_1o | 2013-10-07 18:33:09 |
| 5 | sean | 2CCEx15_1o | 2013-10-07 18:33:38 |
| 27 | sean | 2CCEx15_1o | 2013-10-07 18:37:38 |
| 212 | sean | 2CCEx15_1o | 2013-10-14 18:36:05 |
| 236 | sean | 2CCEx15_1o | 2013-10-21 17:59:56 |
| 237 | sean | 2CCEx15_1o | 2013-10-21 18:00:55 |
| 281 | sean | 2CCEx15_1o | 2013-10-29 15:58:40 |
| 287 | sean | 2CCEx15_1o | 2013-10-29 19:24:15 |
| 330 | sean | 2CCEx15_1o | 2013-10-31 14:39:33 |
| 615 | sean | 2CCEx15_1o | 2013-12-16 22:46:59 |
| 616 | sean | 2CCEx15_1o | 2013-12-16 22:54:46 |
+-------------+---------------+------------+---------------------+
我想为名为 bucket_id 的列的每个唯一值选择一行,其中所选行具有最新的时间戳。
我已经根据之前对类似问题的回答尝试了以下方法,但一定有问题
SELECT takes.* FROM takelist as takes
INNER JOIN (
SELECT takelist_id, max(ts) max_ts, bucket_id
FROM takelist
WHERE producer_name='sean'
GROUP BY bucket_id
) latest_take
ON takes.takelist_id=latest_take.takelist_id
AND takes.ts=latest_take.max_ts
【问题讨论】:
您的子查询依赖于 mysql 特定的行为,并且您的语句将导致大多数/所有其他 RDBMS 引发语法错误:您列出的列既不在GROUP BY
中也不是聚合函数(如MAX()
)。在 MySQL 中,takelist_id
在这种情况下的内容本质上是“不确定的”——它在很大程度上取决于您定义的索引、正在执行的查询等,并且完全取决于优化器的心血来潮。在这种情况下没有保证特定行为的好方法,因此请尽量避免使用此“功能”。
【参考方案1】:
您的查询已结束。但是您使用的是 id 而不是时间戳:
SELECT takes.*
FROM takelist takes INNER JOIN
(SELECT max(ts) as max_ts, bucket_id
FROM takelist
WHERE producer_name = 'sean'
GROUP BY bucket_id
) latest_take
ON takes.ts = latest_take.max_ts and takes.bucket_id = latest_take.bucket_id;
在原始公式中选择了任意takelist_id
。它可能不是你想要的。
【讨论】:
谢谢 - 现在完美。 @user3145007 如果bucket_id
发生变化会怎样?根据我的说法,对于所有 bucket_ids,此查询将仅检查带有 takelist 表的 TIMESTAMP,因此查询可能会为每个 bucket_ids 返回多个记录。
Gordon - 我认为您的意思是将 bucket_id
添加到联接中?【参考方案2】:
试试这个:
SELECT t.*
FROM takelist AS t
INNER JOIN (SELECT MAX(ts) max_ts, bucket_id
FROM takelist WHERE producer_name='sean'
GROUP BY bucket_id
) lt ON t.bucket_id=lt.bucket_id AND t.ts=lt.max_ts;
或
SELECT *
FROM (SELECT * FROM takelist WHERE producer_name='sean' ORDER BY bucket_id, ts DESC) A
GROUP BY bucket_id
【讨论】:
请注意,我会非常对您的第二个选项持怀疑态度,因为我不确定预期的行为(获得“每组第一行”)是保证。 @Clockwork-Muse In MySQL 根据我使用 MySQL 的经验得到保证。以上是关于mysql选择组中的最新时间戳的主要内容,如果未能解决你的问题,请参考以下文章
基于组 ID 子集的时间戳列的组中的最后一行 - Postgres