首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在进行分析查询时,如何避免DISTINCT作为拐杖?

在进行分析查询时,如何避免DISTINCT作为拐杖?
EN

Stack Overflow用户
提问于 2013-06-06 12:14:34
回答 2查看 2.3K关注 0票数 1

我有一个查询,我认为它有一个相当常见的模式。考虑下表:

代码语言:javascript
复制
id | val | ts
---+-----+-------
 a |  10 | 12:01
 a |  12 | 12:05
 a |   9 | 12:15
 b |  30 | 12:03

我想获取每个id的时间戳的最新值。有几种方法可以做到这一点:

代码语言:javascript
复制
-- 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,而不会以这样一个丑陋的查询结束?

EN

回答 2

Stack Overflow用户

发布于 2013-06-06 17:44:27

如果仅按id分组

代码语言:javascript
复制
select
    id, max(ts)
  from x
  group by id 
  order by id

如果组由idval组成

代码语言:javascript
复制
select
    id, val, max(ts)
  from
    x
  group by id, val
  order by id, val

因此,我不会在子查询中使用put aggregate (可能会更慢),我也不会使用window aggregate函数(因为您可以使用普通的group bymax),我也不会使用distinct,因为这意味着不同的东西(至少对我来说)。

如果您在id上进行分组,并且您想要val的一个值,我建议使用窗口聚合函数,因为您必须以某种方式定义要选择的val:而这个意图属于紧跟在partition by之后的order by

从维护的角度来看,我认为窗口聚合函数真正描述了您的意图-您想要实现的目标。其他查询以某种方式隐藏了它们的意图。就我个人而言,当我读到你的问题时,第二个是最容易理解的。

从性能的角度来看,我可以确认窗口聚合是快速的(至少在我的情况下是这样)。也可能是优化器从语法中受益。

票数 1
EN

Stack Overflow用户

发布于 2013-06-06 19:36:39

这是最简单、最快的方法:

代码语言:javascript
复制
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中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16953590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档