我有一个类似调用者makerar的表格
cname | wmname | avg
--------+-------------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
我想为每个cname选择最大的avg。
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
我该如何着手解决这个问题呢?
注意:这个表是在前面的操作中创建的VIEW。
对我来说,这不是一个“常见的聚合问题”,而只是一个错误的SQL查询。“为每个cname选择最大平均值…”的唯一正确答案是
SELECT cname, MAX(avg) FROM makerar GROUP BY cname;
结果将是:
cname | MAX(avg)
--------+---------------------
canada | 2.0000000000000000
spain | 5.0000000000000000
这个结果大体上回答了“每个组的最佳结果是什么?”的问题。我们看到,西班牙最好的结果是5,加拿大最好的结果是2。这是真的,没有错误。
如果我们还需要显示wmname,我们必须回答这个问题:“从结果集中选择wmname的规则是什么?”让我们稍微改变一下输入数据来澄清这个错误:
cname | wmname | avg
--------+--------+-----------------------
spain | zoro | 1.0000000000000000
spain | luffy | 5.0000000000000000
spain | usopp | 5.0000000000000000
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;?应该是西班牙+路飞还是西班牙+乌索普?为什么?如果有几个合适的wmname,查询中没有确定如何选择“更好的”wmname,因此结果也没有确定。这就是为什么SQL解释器返回一个错误-查询是不正确的。
换句话说,“谁是西班牙组最好的?”这个问题没有正确答案。路飞不比usopp好,因为usopp有同样的“分数”。
对我来说,这不是一个“常见的聚合问题”,而只是一个错误的SQL查询。“为每个cname选择最大平均值…”的唯一正确答案是
SELECT cname, MAX(avg) FROM makerar GROUP BY cname;
结果将是:
cname | MAX(avg)
--------+---------------------
canada | 2.0000000000000000
spain | 5.0000000000000000
这个结果大体上回答了“每个组的最佳结果是什么?”的问题。我们看到,西班牙最好的结果是5,加拿大最好的结果是2。这是真的,没有错误。
如果我们还需要显示wmname,我们必须回答这个问题:“从结果集中选择wmname的规则是什么?”让我们稍微改变一下输入数据来澄清这个错误:
cname | wmname | avg
--------+--------+-----------------------
spain | zoro | 1.0000000000000000
spain | luffy | 5.0000000000000000
spain | usopp | 5.0000000000000000
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;?应该是西班牙+路飞还是西班牙+乌索普?为什么?如果有几个合适的wmname,查询中没有确定如何选择“更好的”wmname,因此结果也没有确定。这就是为什么SQL解释器返回一个错误-查询是不正确的。
换句话说,“谁是西班牙组最好的?”这个问题没有正确答案。路飞不比usopp好,因为usopp有同样的“分数”。
SELECT t1.cname, t1.wmname, t2.max
FROM makerar t1 JOIN (
SELECT cname, MAX(avg) max
FROM makerar
GROUP BY cname ) t2
ON t1.cname = t2.cname AND t1.avg = t2.max;
使用rank()窗口函数:
SELECT cname, wmname, avg
FROM (
SELECT cname, wmname, avg, rank()
OVER (PARTITION BY cname ORDER BY avg DESC)
FROM makerar) t
WHERE rank = 1;
Note
每个组都保留多个最大值。如果你想要每组只有一条记录,即使avg等于max的记录不止一条,你应该检查@ypercube的答案。