与HAVING子句的行为混淆

时间:2017-02-10 08:23:56

标签: sql group-by having

我无法理解以下查询的行为:

select max(avg(salary)) from employees
group by first_name
having avg(salary) >= max(salary);

将结果打印为 17000 。但如果max(薪水) 24000 不应该是空的结果。如果我更换""> =""用">"它将结果打印为 NULL

如果我更换"> ="使用"<",然后在结果中打印13100。

以下是员工表:

TJ      2100
Steven  2200
Hazel   2200
James   2400
Ki      2400
Karen   2500
James   2500
Joshua  2500
Peter   2500
Martha  2500
Randall 2500
Guy     2600
Randall 2600
Donald  2600
Douglas 2600
Irene   2700
John    2700
Sigal   2800
Mozhe   2800
Girard  2800
Vance   2800
Shelli  2900
Michael 2900
Timothy 2900
Anthony 3000
Kevin   3000
Alex    3100
Curtis  3100
Jean    3100
Alana   3100
Julia   3200
Stephen 3200
Winston 3200
Samuel  3200
Laura   3300
Jason   3300
Julia   3400
Trenna  3500
Renske  3600
Jennife 3600
Kelly   3800
Britney 3900
Sarah   4000
Alexis  4100
Diana   4200
Nandita 4200
Jennife 4400
David   4800
Valli   4800
Kevin   5800
Bruce   6000
Pat     6000
Sundita 6100
Amit    6200
Charles 6200
Sundar  6400
Shanta  6500
Susan   6500
David   6800
Luis    6900
Oliver  7000
Sarath  7000
Kimbe   7000
Mattea  7200
Eliza   7300
William 7400
Nanette 7500
Louise  7500
Ismael  7700
Jose    7800
Payam   7900
Matthew 8000
Christ  8000
Lindsey 8000
John    8200
Adam    8200
William 8300
Jack    8400
Jonath  8600
Alyssa  8800
Alex    9000
Daniel  9000
Peter   9000
Allan   9000
Patrick 9500
Danie   9500
David   9500
Tayler  9600
Hermann 10000
Harris  10000
Janette 10000
Peter   10000
Clara   10500
Eleni   10500
Gerald  11000
Den     11000
Ellen   11000
Lisa    11500
Alberto 12000
Shelley 12008
Nancy   12008
Michael 13000
Karen   13500
John    14000
Lex     17000
Neena   17000
Steven  24000

2 个答案:

答案 0 :(得分:3)

您正在表格中按First_name分组

对于Neena,max(salary) = 17000avg(salary)=17000

因此,>=与查询中的条件匹配,并返回17000

>=替换为>的地方变为NULL。

史蒂文,马克斯(薪水)= 24000,AVG(薪水)=(24000 + 2200)/ 2 = 13100

因此,将>=替换为<会返回13100

  

注意:在此处按列名称分组first_name起着关键作用   这里。 SELECT中的所有聚合函数以及having子句,   适用于每位员工,而不是整张桌子。

答案 1 :(得分:0)

如果你想比较一个员工的平均工资(这真的有意义吗?当然一个员工在某个时间点只有一个工资?)那么这可能会有所帮助

WITH
 employees (first_name,salary)
 AS
  (SELECT 'TJ',2100 FROM dual UNION ALL
   SELECT 'Steven',2200 FROM dual UNION ALL
   SELECT 'Hazel',2200 FROM dual UNION ALL
   SELECT 'James',2400 FROM dual UNION ALL
   SELECT 'Ki',2400 FROM dual UNION ALL
   SELECT 'Karen',2500 FROM dual UNION ALL
   SELECT 'James',2500 FROM dual UNION ALL
   SELECT 'Joshua',2500 FROM dual UNION ALL
   SELECT 'Peter',2500 FROM dual UNION ALL
   SELECT 'Martha',2500 FROM dual 
  )
SELECT
 first_name
,mean_salary_all_emps
,AVG(salary)
FROM
 (SELECT
   first_name
  ,salary
  ,AVG(salary) OVER ()  mean_salary_all_emps
  FROM
   employees
 )
WHERE 1=1
GROUP BY 
 first_name
,mean_salary_all_emps
HAVING  AVG(salary) > mean_salary_all_emps
;