ORA-00979不是Group By函数错误

时间:2015-01-01 11:17:33

标签: oracle ora-00979

Iam尝试从表中选择2个值,Employee emp_name,emp_location按emp_location分组,我知道按功能分组的列需要在select子句中,但我想知道是否还有其他在单个查询中获取这些值的方法。

我的目的是根据年龄选择每个地点只有一名员工。 样本查询

select emp_name,emp_location 
from Employee 
where emp_age=25 
group by emp_location

请在这方面提供帮助。

非常感谢所有回答此问题的人。我将尝试学习这些窗口函数,因为它们非常方便。

3 个答案:

答案 0 :(得分:2)

  

ORA-00979不是Group By功能错误

GROUP BY子句中只允许SELECT子句中指定的聚合函数列。

在这方面,Oracle密切关注SQL标准。但是,正如您在评论中注意到的那样,其他一些RDBMS在这方面不如Oracle严格。例如,引用MySQL's documentation(强调我的):

  

MySQL扩展了GROUP BY的使用,因此选择列表可以引用GROUP BY子句中未命名的非聚合列。 [...]

     

但是,当GROUP BY中未命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此< strong>除非它们相同,否则所选择的值是不确定的。

因此,在推荐的用例中,将额外的列添加到GROUP BY子句将导致相同的结果。


select emp_name,emp_location 
--     ^^^^^^^^
--   this is *not* part of the ̀`GROUP BY` clause
from Employee 
where emp_state=25 
group by emp_location

也许您正在寻找:

...
group by emp_location, emp_name

答案 1 :(得分:2)

这在MySQL中而不是在Oracle中工作的原因是因为在Oracle以及大多数其他数据库中,您需要在group by子句中指定字段(或表达式),或者它必须是一个聚合,它将组中所有值的值组合成一个值。例如,这将起作用:

select max(emp_name),emp_location 
from Employee 
where emp_age=25 
group by emp_location

但是,它可能不是最好的解决方案。如果您只想要名称,它将起作用,但是当您希望为员工提供多个字段时,您会遇到麻烦。在那种情况下,max不会做到这一点。在下面的查询中,您可能会得到一个与姓氏不匹配的名字。

select max(emp_firstname), max(emp_lastname), emp_location 
from Employee 
where emp_age=25 
group by emp_location 

解决方法是使用窗口函数(分析函数)。有了这些,您可以为每条记录生成一个值,而不会立即减少记录数。例如,使用窗口max功能,您可以为名为John的人选择最大年龄,并在结果中的每个John旁边显示该值,即使他们没有年龄。

某些功能(如rankdense_rankrow_number可用于为每位员工生成一个号码,然后您可以使用该号码进行过滤。在下面的示例中,我为每个位置(分区依据)创建了一个这样的计数器,并按顺序排列,在本例中为name和id。您也可以指定其他字段,例如,如果您希望每个位置的每个年龄段都有一个名称,则可以在partition by中指定年龄和位置。如果您想要每个位置的最老员工,则可以删除where emp_age=25order by emp_age desc

select
  *
from
  (select 
    emp_name, emp_location,
    dense_rank() over (partition by emp_location order by emp_name, emp_id) as emp_rank
  from Employee 
  where emp_age=25)
where
  emp_rank = 1

答案 2 :(得分:0)

select emp_name,emp_location
from Employee
where emp_age=25
group by emp_name,emp_location

select max(emp_name) emp_name,emp_location
from Employee
where emp_age=25
group by emp_location