PostgreSQL MAX和GROUP BY

Pro*_*Dev 37 sql postgresql group-by max greatest-n-per-group

我有一张桌子id,yearcount.

我想得到MAX(count)每个id并保持year它发生的时间,所以我做这个查询:

SELECT id, year, MAX(count)
FROM table
GROUP BY id;
Run Code Online (Sandbox Code Playgroud)

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

错误:列"table.year"必须出现在GROUP BY子句中或用于聚合函数

所以我尝试:

SELECT id, year, MAX(count)
FROM table
GROUP BY id, year;
Run Code Online (Sandbox Code Playgroud)

但是,它没有做MAX(count),它只是显示表格.我想是因为分组的时候yearid,它得到最大的id是特定年份的.

那么,我该如何编写该查询呢?我想要得到idMAX(count),并在今年这种情况发生的时候.

Erw*_*ter 64

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

SELECT DISTINCT ON (1)
       id, count, year
FROM   tbl
ORDER  BY 1, 2 DESC, 3;
Run Code Online (Sandbox Code Playgroud)

数字表示SELECT列表中的序号位置.为清晰起见,您可以拼写列名称:

SELECT DISTINCT ON (id)
       id, count, year
FROM   tbl
ORDER  BY id, count DESC, year;
Run Code Online (Sandbox Code Playgroud)

结果按顺序排列id,欢迎或不欢迎.在任何情况下,它都比"未定义"更好.

它还以明确的方式打破了关系(当多年共享相同的最大数量时):选择最早的年份.如果你不在乎,下降yearORDER BY.或者选择最近一年year DESC.

在这个密切相关的答案中有更多解释,链接,基准和可能更快的解决方案:

旁白:在实际查询中,您不会使用某些列名称.id是列名的非描述性反模式,count标准SQL中保留字和Postgres中的聚合函数.


a_h*_*ame 44

select *
from (
  select id, 
         year,
         thing,
         max(thing) over (partition by id) as max_thing
  from the_table
) t
where thing = max_thing
Run Code Online (Sandbox Code Playgroud)

要么:

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);
Run Code Online (Sandbox Code Playgroud)

要么

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
Run Code Online (Sandbox Code Playgroud)

或(与前一个不同的符号相同)

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
Run Code Online (Sandbox Code Playgroud)