我有一张桌子看起来像是打电话的"makerar"

 cname  | wmname |          avg           
--------+-------------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

我想 for each cname Select 最大平均值.

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

但我会出错,

ERROR:  column "makerar.wmname" must appear in the GROUP BY clause or be used in an   aggregate function 
LINE 1: SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

所以我这么做

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname, wmname;

然而,这不会给出预期的结果,下面显示的输出不正确.

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

实际结果应该是

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

我如何着手解决这个问题?

注意:此表是根据以前的操作创建的视图.

推荐答案

是的,这是一个常见的聚合问题.在SQL3 (1999)之前,所选字段必须出现在GROUP BY子句[*]中.

要解决此问题,必须计算子查询中的聚合,然后将其与自身连接,以获得需要显示的其他列:

SELECT m.cname, m.wmname, t.mx
FROM (
    SELECT cname, MAX(avg) AS mx
    FROM makerar
    GROUP BY cname
    ) t JOIN makerar m ON m.cname = t.cname AND t.mx = m.avg
;

 cname  | wmname |          mx           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

但也可以使用窗口函数,这看起来更简单:

SELECT cname, wmname, MAX(avg) OVER (PARTITION BY cname) AS mx
FROM makerar
;

这个方法唯一的一点是,它将显示所有记录(窗口函数不分组).但它会在每一行显示正确的(即cname级最大值)MAX,因此这取决于您:

 cname  | wmname |          mx           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  |     5.0000000000000000
 spain  | usopp  |     5.0000000000000000

可以说不那么优雅的解决方案是,只显示与最大值匹配的(cname, wmname)个元组:

SELECT DISTINCT /* distinct here matters, because maybe there are various tuples for the same max value */
    m.cname, m.wmname, t.avg AS mx
FROM (
    SELECT cname, wmname, avg, ROW_NUMBER() OVER (PARTITION BY avg DESC) AS rn 
    FROM makerar
) t JOIN makerar m ON m.cname = t.cname AND m.wmname = t.wmname AND t.rn = 1
;


 cname  | wmname |          mx           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

[*]:有趣的是,尽管规范允许 Select 非分组字段,但主要引擎似乎并不喜欢它.Oracle和SQLServer根本不允许这样做.Mysql以前默认允许,但现在从5.7开始,管理员需要在服务器配置中手动启用此选项(ONLY_FULL_GROUP_BY),才能支持此功能...

Sql相关问答推荐

神秘的日期转换

使用group by后我的平均输出不是我想要的

postgresql插入json不工作

如何通过比较不同表中相同ID S的值来筛选ID为S的列表?

前面的语句不喜欢AND LIKE?当try 更新使用ID和日期过滤的表时

将主表与历史表连接以获取主表的当前汇率以及历史表中的上一个和最后一个汇率

如何在SQL中更新Json字符串

从列中提取子字符串的ORDER BY CASE语句

是否可以为表中的所有列生成散列值?

HAVING子句内部过滤的正确方法

优化Postgres搜索未知长度的子串

从JSON值数组创建扁平数组Athena

配置单元查询失败:无法识别';附近的输入;LEFT'';(select子句中的';';col'

如何在android房间中进行多个加入

Spark / Hive:如何获取列中正值的百分比?

更新之前如何获得价值

PostgreSQL分割字符串为子词并判断其是否存在于其他字符串中

基于源表的 SQL INSERT、UPDATE 和 DELETE

如何通过存储过程将 root 的下一个子 node 作为父 node ?

为什么 Oracle 在一个查询中对同一张表同时执行 TABLE SCAN 和 INDEX UNIQUE SCAN?