select 复制具有最大时间戳的行的最有效方法

most efficient way to select duplicate rows with max timestamp

假设我有一个名为 t 的 table,就像

id  content  time
1     'a'     100
1     'a'     101
1     'b'     102
2     'c'     200
2     'c'     201

id是重复的,同样的id,内容也可能是重复的。现在我想 select 为每个 id 具有最大时间戳的行,这将是

id  content  time
1      'b'    102
2      'c'    201

这是我目前的解决方案:

select t1.id, t1.content, t1.time 
from (
  select id, content, time from t 
) as t1 
right join (
  select id, max(time) as time from t group by id
) as t2 
on t1.id = t2.id and t1.time = t2.time;

但这对我来说效率不高。因为理论上执行select id, max(time) as time from t group by id的时候,我要的行已经定位了。 right join 带来了额外的 O(n^2) 时间成本,这似乎是不必要的。

那么有没有更有效的方法,或者我有什么误解?

使用DISTINCT ON:

SELECT DISTINCT ON (id) id, content, time
FROM yourTable
ORDER BY id, time DESC;

在 Postgres 上,这通常是编写查询的最高性能方式,它应该优于 ROW_NUMBER 和其他方法。

以下索引可能会加速此查询:

CREATE INDEX idx ON yourTable (id, time DESC, content);

如果使用这个索引,Postgres 会为每个 id 快速找到具有最晚时间的记录。该索引还涵盖了 content 列。

试试这个

SELECT a.id, a.content, a.time FROM t AS a
INNER JOIN (
    SELECT a.content, MAX(a.time) AS time FROM t
    GROUP BY a.content
) AS b ON a.content = b.content AND a.time = b.time