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
请在这方面提供帮助。
非常感谢所有回答此问题的人。我将尝试学习这些窗口函数,因为它们非常方便。
答案 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旁边显示该值,即使他们没有年龄。
某些功能(如rank
,dense_rank
和row_number
可用于为每位员工生成一个号码,然后您可以使用该号码进行过滤。在下面的示例中,我为每个位置(分区依据)创建了一个这样的计数器,并按顺序排列,在本例中为name和id。您也可以指定其他字段,例如,如果您希望每个位置的每个年龄段都有一个名称,则可以在partition by
中指定年龄和位置。如果您想要每个位置的最老员工,则可以删除where emp_age=25
和order 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