【发布时间】:2013-06-06 04:14:34
【问题描述】:
我有一个查询,我认为它具有相当普遍的模式。考虑这张表:
id | val | ts
---+-----+-------
a | 10 | 12:01
a | 12 | 12:05
a | 9 | 12:15
b | 30 | 12:03
我想通过时间戳获取每个 id 的最新值。一些方法可以做到:
-- where in aggregate subquery
-- we avoid this because it's slow for our purposes
select
id, val
from t
where (id, ts) in
(select
id,
max(ts)
from t
group by id);
-- analytic ranking
select
id, val
from
(select
row_number() over (partition by id order by ts desc) as rank,
id,
val
from t) ranked
where rank = 1;
-- distincting analytic
-- distinct effectively dedupes the rows that end up with same values
select
distinct id, val
from
(select
id,
first_value(val) over (partition by id order by ts desc) as val
from t) ranked;
分析排名查询感觉像是最容易提出有效查询计划的查询。但在美学和维护方面,它非常难看(尤其是当表的值列不止 1 个时)。 在生产中的一些地方,当测试表明性能相当时,我们会使用独特的分析查询。
有没有什么方法可以做 rank = 1 之类的事情,而不会得到如此丑陋的查询?
【问题讨论】:
-
如果有像
a, 10, 13:45这样的另一行,你期望得到什么结果? (所以有些记录 id 和 val 的组合不是唯一的)。 -
@Beryllium 我提出的所有 3 个查询都应该按时间戳选择最新值。因此,如果将您的行添加到示例表中,它应该可以很好地处理它。如果同一值有 2 个相同的时间戳,则会导致聚合查询出现问题。
-
“拐杖”+1! Distinct 是最广泛使用的消除重复项的工具,但实际上查询存在问题。有合法的用途,但对我来说,每当我看到它时,它都会在查询中显示一个危险信号。
-
Mysql 有一个巧妙的解决方法。您只想查看 postgres 答案吗?
标签: sql postgresql distinct vertica window-functions