PostgreSQL MAX 和 GROUP BY

Posted

技术标签:

【中文标题】PostgreSQL MAX 和 GROUP BY【英文标题】:PostgreSQL MAX and GROUP BY 【发布时间】:2012-10-30 19:21:21 【问题描述】:

我有一张桌子,上面有 idyearcount

我想为每个id 获取MAX(count) 并在它发生时保留year,所以我进行了以下查询:

SELECT id, year, MAX(count)
FROM table
GROUP BY id;

不幸的是,它给了我一个错误:

错误:列“table.year”必须出现在 GROUP BY 子句中,否则 在聚合函数中使用

所以我试试:

SELECT id, year, MAX(count)
FROM table
GROUP BY id, year;

但是,它不会做MAX(count),它只是按原样显示表格。我想是因为当按yearid 分组时,它会获得该特定年份的id 的最大值。

那么,我该如何编写该查询?我想得到id´s MAX(count) 以及发生这种情况的年份。

【问题讨论】:

如果 id,year 是唯一的,max(thing)thing 相同。另请注意,“计数”是一个关键字,(在某些方言中,年份也是如此,IIRC) 您希望每个 id 获得哪一年?没有“年”,有不止一个,也许你想要MAX(year) 是的,它们是独一无二的,所以我明白了。我想获得 ids MAX(thing) 并且还想看看发生在哪一年。 (我的代码中没有写计数,只是一个例子) 我想得到那个 ID 最大化“事物”列的年份 【参考方案1】:

最短(也可能是最快)查询将使用DISTINCT ON,这是 SQL 标准 DISTINCT 子句的 PostgreSQL 扩展:

SELECT DISTINCT ON (1)
       id, count, year
FROM   tbl
ORDER  BY 1, 2 DESC, 3;

数字指的是SELECT 列表中的序号位置。为了清楚起见,您可以拼出列名:

SELECT DISTINCT ON (id)
       id, count, year
FROM   tbl
ORDER  BY id, count DESC, year;

结果由id 等排序,这可能会或可能不会受到欢迎。在任何情况下都比“未定义”要好。

它还以明确定义的方式打破联系(当多个年份共享相同的最大计数时):选择最早的年份。如果您不在乎,请从ORDER BY 中删除year。或者通过year DESC 选择最近的年份。

对于每个id 许多 行,其他查询技术(快得多)。见:

Select first row in each GROUP BY group? Optimize GROUP BY query to retrieve latest row per user

【讨论】:

查询执行时间更短的完美解决方案。我尝试分组并获取最大数据。但它很慢。谢谢你欧文.. 我还有另一个同样的问题,我的 MAX() 有两个输出,所以输出只是第一个出现的输出,我想同时得到它们,我该怎么做?跨度> 也很好地阅读了可能更好的替代方案和讨论wiki.postgresql.org/wiki/Loose_indexscan【参考方案2】:
select *
from (
  select id, 
         year,
         thing,
         max(thing) over (partition by id) as max_thing
  from the_table
) t
where thing = max_thing

或:

select t1.id,
       t1.year,
       t1.thing
from the_table t1
where t1.thing = (select max(t2.thing) 
                  from the_table t2
                  where t2.id = t1.id);

select t1.id,
       t1.year,
       t1.thing
from the_table t1
  join ( 
    select id, max(t2.thing) as max_thing
    from the_table t2
    group by id
  ) t on t.id = t1.id and t.max_thing = t1.thing

或(与前面相同,但符号不同)

with max_stuff as (
  select id, max(t2.thing) as max_thing
  from the_table t2
  group by id
) 
select t1.id, 
       t1.year,
       t1.thing
from the_table t1
  join max_stuff t2 
    on t1.id = t2.id 
   and t1.thing = t2.max_thing

【讨论】:

@user1504577:当多个年份共享最大计数时,所有这些查询都会为每个 id 返回多个值。在这种常见情况下,您必须定义您想要的内容。显示所有?选一个?最新的/最早的/什么?在一列中显示年份列表? @a_horse_with_no_name 你能解释一下这些查询的优缺点吗? 选择这个答案,因为它提供了适用于不同 SQL 引擎的查询,在服务器之间迁移已经像 f**k 一样烦人。

以上是关于PostgreSQL MAX 和 GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章

postgreSQL使用sql归一化数据表的某列,以及出现“字段 ‘xxx’ 必须出现在 GROUP BY 子句中或者在聚合函数中”错误的可能原因之一

sql:group by和 max

PostgreSQL GROUP BY 语句

PostgreSQL GROUP BY 语句

mysql group by和max [重复]

非聚合与 MAX 和 GROUP BY