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
假设我有一个名为 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