我有一个餐桌员工
id name salary city
1 ram 50000 c1
2 sham 20000 c2
3 jadu 80000 c1
4 madhu 90000 c4
5 hari 10000 c2
6 gopal 34000 c3
7 komal 55000 c3
8 bappa 98000 c4
Run Code Online (Sandbox Code Playgroud)
查询哪个城市的收入最高。我试过
SELECT city, SUM(salary) AS maxSalary
FROM employee GROUP BY city ORDER BY salary DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
它工作正常,但如果有多个最大收入城市,那么它不会输出其他最大城市,只输出第一个。
所以我试过这个查询
SELECT city, MAX(totalSalary) maxSalary
FROM( SELECT city, SUM(salary) AS totalSalary FROM employee GROUP BY city ) AS tempTable
Run Code Online (Sandbox Code Playgroud)
它正在给予
city max
c1 188000
Run Code Online (Sandbox Code Playgroud)
但正确的是
city max
c4 188000
Run Code Online (Sandbox Code Playgroud)
这意味着它正在输出表的第一个城市名称,c1但不是正确的最大收入城市名称,即c4. 什么是正确的查询?
您向数据库发送了错误的查询。您遇到了手册中描述的 mysql 扩展。像这样的查询
SELECT city, MAX(salary)
from employee
Run Code Online (Sandbox Code Playgroud)
在标准 SQL 中不起作用。它在Oracle 中引发错误(错误消息:“ORA-00937:不是单组组函数”),在MSSqlServer 2012 中(错误消息:“列'employee.city' 在选择列表中无效,因为它未包含在内)在聚合函数或 GROUP BY 子句中”)或postgresql(错误消息:“错误:列“employee.city”必须出现在 GROUP BY 子句中或用于聚合函数中”)。
在选择列表中的标准 SQL 表达式中,只能是也在 group by 子句和聚合函数中使用的列的表达式。group by 子句中使用的列值对于这些组中的所有行都相同。聚合对于一个组也是唯一的。选择为每个组返回一行,其中包含该组的唯一定义值。
如果聚合查询没有 group by 子句,则只有一组行。
该标准不允许在聚合查询的选择列表中使用任意列,因为它的值不是唯一定义的:该列对于查询的行具有不同的值,因此查询应该为该组返回哪一个?
在 mysql 中有一个扩展,如果表达式中的列(不是聚合函数表达式中的列)不在 group by 子句中,则该组的 select 语句返回的值是该组的任意行。
所以查询
SELECT city, MAX(salary)
from employee
Run Code Online (Sandbox Code Playgroud)
返回所有员工的工资和其中一行所在城市的总和。但是查询只返回一个记录,因为它是一个聚合查询,并且只有一个组包含员工表中的所有记录。
查询
SELECT city, MAX(salary)
from employee
group by city
Run Code Online (Sandbox Code Playgroud)
为每个城市返回一行,其中包含城市和每个城市的工资。
查询
SELECT city, salary
from employee
group by city
Run Code Online (Sandbox Code Playgroud)
返回每个城市的行和该城市任意雇员的礼节。服务器决定选择哪个城市的雇员。
查询
SELECT city, zipcode
from employee
group by city
Run Code Online (Sandbox Code Playgroud)
还为每个城市返回一行,并带有该城市的邮政编码。如果我们假设每个城市只有一个邮政编码,那么城市定义的每个组的行都包含相同的邮政编码。因此独立于服务器选择重新调整的邮政编码将始终是城市的邮政编码。
在标准 SQL 中,此查询将写为
SELECT city, zipcode
from employee
group by city, zipcode
Run Code Online (Sandbox Code Playgroud)
创造预期的结果
group by city,zipcode并group city定义相同的组,因为 zipcdoe 一个城市之间是一一对应的。
查询
SELECT city, SUM(salary)
from employee
group by city
Run Code Online (Sandbox Code Playgroud)
将不仅包含所需的行,而且包含更多。
一种从此查询中过滤掉所需行的方法如下
SELECT city, SUM(salary)
from employee
group by city
having SUM(salary) >= all (select SUM(salary) city_salary
from employee
group by city)
Run Code Online (Sandbox Code Playgroud)
还有其他过滤方法。
可以通过以下查询找到最大的工资总额
select MAX(city_salary)
from (select SUM(salary) city_salary
from employee
group by city) tab
Run Code Online (Sandbox Code Playgroud)
(注意:在 Oracle 中同样可以通过
select MAX(SUM(salary)) city_salary
from employee
group by city
Run Code Online (Sandbox Code Playgroud)
)
所以我们可以用它来过滤掉需要的:
SELECT city, SUM(salary)
from employee
group by city
having SUM(salary) = (select MAX(city_salary)
from (select SUM(salary) city_salary
from employee
group by city) tab)
Run Code Online (Sandbox Code Playgroud)
@Mihai 在他的评论中已经提出了这个解决方案。
| 归档时间: |
|
| 查看次数: |
43121 次 |
| 最近记录: |