使用聚合函数Oracle对记录进行分组

时间:2013-07-04 07:04:57

标签: oracle oracle11g oracle10g

我在Oracle中有一个表,如下所示

   CREATE TABLE Employees(EmpId INT, 
                          EmpName VARCHAR2(30), 
                          Designation VARCHAR2(30), 
                          Salary INT);

我在表格中插入了行,如下所示

INSERT ALL 
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(101, 'Scott', 'Clerk', 2500)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(102, 'Mac', 'Manager', 5000)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(103, 'Steave', 'Clerk', 1500)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(104, 'John', 'Clerk', 1500)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(105, 'Jack', 'Analyst', 2500)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(106, 'Paul', 'Manager', 4500)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(107, 'Ryan', 'Clerk', 1250)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(108, 'Phillipe', 'Analyst', 3150)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(109, 'Clark', 'Clerk', 1200)
   INTO Employees(EmpId, EmpName, Designation, Salary)VALUES(110, 'Arnold', 'Clerk', 1100)
   SELECT * FROM dual;

以下是表格的简短概述

enter image description here

现在,我希望将按名称分组的收入最高的人分组为

EmpName   Designation  Salary
Phillipe  Analyst      3150 
Scott     Clerk        2500
Mac       Manager      5000

我希望通过指定获得empName,指定和最高薪水。

我尝试了以下查询,但它带来了所有记录

SELECT EmpName, Designation, max(Salary) AS msal
  FROM Employees
 GROUP BY Designation, EmpName 
 ORDER BY Designation, msal DESC

感谢回复

3 个答案:

答案 0 :(得分:3)

具有相关子查询的版本

SELECT EmpName, Designation, Salary
  FROM Employees e
 WHERE Salary = (SELECT MAX(Salary) 
                   FROM Employees 
                  WHERE Designation = e.Designation)

JOIN

SELECT e.EmpName, e.Designation, e.Salary
  FROM Employees e JOIN 
(
  SELECT Designation, MAX(Salary) Salary
    FROM Employees 
   GROUP BY Designation
) q ON e.Designation = q.Designation
   AND e.Salary = q.Salary

以下是两个查询的 SQLFiddle 演示

答案 1 :(得分:2)

SELECT 
  max(EmpName) keep (dense_rank last order by salary) AS EmpName
, Designation
, max(Salary) keep (dense_rank last order by salary)  AS Salary
FROM Employees
GROUP BY Designation
;

答案 2 :(得分:2)

假设您的意思是“指定”而不是“部门”,您可以使用分析查询来执行此操作:

SELECT EmpName, Designation, Salary
FROM (
    SELECT EmpName, Designation, Salary,
        RANK() OVER (PARTITION BY Designation ORDER BY Salary DESC) AS rn
      FROM Employees
)
WHERE rn = 1
ORDER BY Designation;

EMPNAME                        DESIGNATION                        SALARY
------------------------------ ------------------------------ ----------
Phillipe                       Analyst                              3150 
Scott                          Clerk                                2500 
Mac                            Manager                              5000 

内部查询对每一行应用排名,1表示每个指定中的最高薪水(并允许绑定)。外部查询然后重新生成结果,仅显示每个设计的排名最高的行。

在你的原始版本中,你group by并没有真正做任何事情,因为它包括有效的所有列 - 除了empid,但除非你有两个同名的人,否则这没有任何区别。您需要找到指定的最大值,然后找到与该最大值匹配的记录,这意味着查看同一个表;例如:

SELECT EmpName, Designation, Salary
  FROM Employees
 WHERE (Designation, Salary) IN (
     SELECT Designation, MAX(Salary)
       FROM Employees
      GROUP BY Designation
  )
ORDER BY Designation;

...或peterm的相关子查询;但我更喜欢分析路线,特别是对于较大的桌子,因为你只打了一次桌子。而且我个人觉得它更清楚。