Pro*_*Dev 37 sql postgresql group-by max greatest-n-per-group
我有一张桌子id,year和count.
我想得到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),它只是显示表格.我想是因为分组的时候year和id,它得到最大的id是特定年份的.
那么,我该如何编写该查询呢?我想要得到id的MAX(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,欢迎或不欢迎.在任何情况下,它都比"未定义"更好.
它还以明确的方式打破了关系(当多年共享相同的最大数量时):选择最早的年份.如果你不在乎,下降year从ORDER 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)