我有一个查询,我认为它有一个相当常见的模式。考虑下表:
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个时)。在生产中的一些地方,当测试表明性能相同时,我们使用区分分析查询。
有没有办法做一些事情,如排名=1,而不会以这样一个丑陋的查询结束?
发布于 2013-06-06 17:44:27
如果仅按id分组
select
id, max(ts)
from x
group by id
order by id如果组由id和val组成
select
id, val, max(ts)
from
x
group by id, val
order by id, val因此,我不会在子查询中使用put aggregate (可能会更慢),我也不会使用window aggregate函数(因为您可以使用普通的group by和max),我也不会使用distinct,因为这意味着不同的东西(至少对我来说)。
如果您在id上进行分组,并且您想要val的一个值,我建议使用窗口聚合函数,因为您必须以某种方式定义要选择的val:而这个意图属于紧跟在partition by之后的order by。
从维护的角度来看,我认为窗口聚合函数真正描述了您的意图-您想要实现的目标。其他查询以某种方式隐藏了它们的意图。就我个人而言,当我读到你的问题时,第二个是最容易理解的。
从性能的角度来看,我可以确认窗口聚合是快速的(至少在我的情况下是这样)。也可能是优化器从语法中受益。
发布于 2013-06-06 19:36:39
这是最简单、最快的方法:
select distinct on (id)
id, ts, val
from t
order by id, ts desc对于每个id,distinc on (仅限Postgresql)将只返回一行。有了order by,你就可以控制哪一个。在本例中是最后一个ts。使用distinct on,您可以在结果集中包含所需的任意数量的列,而不需要中间步骤。distinct on中使用的列必须首先包含在order by中。
https://stackoverflow.com/questions/16953590
复制相似问题