具有聚合功能的SQL HAVING子句?

时间:2019-11-30 19:14:53

标签: mysql sql database

我试图找到公司员工的薪水高于所有员工的平均薪水。我想从一开始就指出,我不希望平均薪水出现在最终结果中,因此我在SELECT语句中忽略了它。这些是我尝试过的事情:

SELECT employee.lastname,employee.firstname,employee.salary FROM employee
GROUP BY employee.salary
HAVING employee.salary > avg(employee.salary);

这将导致结果表为空

但是,尽管有'='符号,但以下内容令人惊讶地返回了公司的所有员工。

SELECT employee.lastname,employee.firstname,employee.salary FROM employee
GROUP BY employee.salary
HAVING employee.salary = avg(employee.salary);

这将再次返回空表:

SELECT employee.lastname,employee.firstname,employee.salary FROM employee
WHERE (SELECT avg(employee.salary) FROM employee 
GROUP BY employee.salary
HAVING employee.salary > AVG(employee.salary));

因此,总结一下这篇文章,我将对正确使用HAVING和聚合函数有一些见解,并对摘要导致空表的原因有一些见解。

5 个答案:

答案 0 :(得分:2)

当您GROUP BY employee.salary时,每个组的平均薪水等于employee.salary,因为该组的所有薪水均相等。
所以条件:

employee.salary > avg(employee.salary)

始终为FALSE,并且您没有任何行, 和条件:

employee.salary = avg(employee.salary)

始终为TRUE,结果是返回所有组。
得到您想要的正确代码是:

SELECT employee.lastname, employee.firstname, employee.salary 
FROM employee
WHERE employee.salary > (SELECT avg(employee.salary) FROM employee);

答案 1 :(得分:1)

如果您将括号放错了位置而导致语法错误,请移去(之前的起始左括号avg(..和分号之前的最后一个封闭括号)

    SELECT  employee.lastname,
  employee.firstname,employee.salary 
   FROM employee
   WHERE employee.salary > 
( SELECT avg(employee.salary) FROM 
   employee);

答案 2 :(得分:1)

尝试一下

SELECT lastname, firstname, salary
FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee)
ORDER BY salary DESC

GROUP BYSELECT子句中仅使用聚合函数时,平均值子查询不需要HAVING

或者使用更精美的东西:

SELECT lastname, firstname, salary
FROM
(
    SELECT lastname, firstname, salary
    , AVG(salary) OVER () AS avg_salary
    FROM employee
) q
WHERE salary > avg_salary

答案 3 :(得分:0)

您可以处理两个集合/表,一个记录级别,另一个集合,即使它们是同一集合:

select e.lastname , e.firstname , e.salary 
FROM employee e, (
    select avg(a.salary) avg_salary
    from employee a
) av
where 1=1
  and e.salary > av.avg_salary
;

答案 4 :(得分:0)

您已通过employee.salary进行汇总。因此,在此查询中:

HAVING employee.salary > avg(employee.salary);

HAVING之前的每一行都具有一个正确的salary值。一个值的平均值-无论组中有多少个-都是该值。由于值不能大于其自身,因此不会返回任何行。

此子句:

 HAVING employee.salary = avg(employee.salary);

是完全一样的东西,除了所有薪水不为{NULL的行都符合此条件。因此,将返回所有行。

正如其他人所提到的,更典型的解决方案是子查询:

select e.*
from employee e
where e.salary > (select avg(e2.salary) from employee e2);

请注意表别名的使用。强烈建议这些。

更现代的解决方案将使用窗口函数:

select . . .   -- select the columns you want
from (select e.*, avg(e.salary) over () as avg_salary
      from employee e
     ) e
where e.salary > avg_salary;