Oracle SQL查询:获得员工的最大销售额

问题描述:

我想查找每位员工的最大销售额(并显示员工的姓名)。在MySQL中,这是非常简单的:Oracle SQL查询:获得员工的最大销售额

select * 
    from employee, sale 
    where employee.id = sale.employee_id 
    group by employee_id 
    order by sale.total desc 

但这几乎人们所期望的东西,它会返回员工列表,并结束与员工行返回最大的销售记录。

但是,当使用group by子句时,Oracle不允许您返回不是group by表达式的列。这是否使我在MySQL中“不可能”在Oracle中做什么?或者有一些解决方法?我想我可以执行某种子查询,但不知道是否有另一种方法可以做到这一点,但构建起来并不那么复杂。

+2

你在做什么在查询中滥用的'MySQL'语法糖,让你选择分组查询中随机取消分组的值。所选行不保证是最高销售额。正如文档所述: 使用此功能时,每个组中的所有行应具有相同的值,以供从GROUP BY部分省略的列相同。服务器可以自由地返回组中的任何值,所以结果是不确定的,除非所有值都相同。 http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html – Quassnoi 2009-09-28 12:57:49

摆脱您的select *并将其替换为您所需的列,然后按所有“未处理”列进行分组。

你会喜欢的东西最终会:

select employee.id, employee.name, max(sale.total) 
from employee, sale 
where employee.id = sale.employee_id 
group by employee.id, employee.name 
order by max(sale.total) desc 

这是一个痛苦 - 我有之前做了很多次 - 但只是

+0

*是为了简洁。在我的非示例中,我实际上指定了列。然而,我确实发现它非常令人讨厌,我需要包括我打算选择的每一列,我必须在group by子句中进行复制。所以,抓住12列将我的SQL语句变成了一些荒谬的怪物。但是,关于max的观点是很好的。 – cgp 2009-09-28 13:15:03

+0

对不起'*'。如果这个人正在缩写或实际执行它,你并不总是从随机的互联网发帖中知道。 我了解这个怪物。由于“好奇”的数据库设计,我不得不在“group by”中包含多达12列。那很不愉快。 – 2009-09-28 13:29:21

+0

好吧,在地址表中最多可以容纳12列。 Addr1,Addr2,City,State,Zip,Country,Long,Lat - 这只是基本的领域。 – cgp 2009-09-28 13:57:12

要获得最大的销售额,您可以使用max函数进行分组。

select e.name, max (s.total) 
    from employee e, sale s 
    where e.id = s.employee_id 
    group by e.name 
    order by s.total desc 
  • 我做了一个假设,即员工的名字是在employee表的name列。我还将员工表和销售表格化为别名。
  • 如果您希望看到员工的总销售额,则可以换出max()并使用sum()代替。
+0

呵呵,呃,我想max是我想要的,但是如何让名字成为好? – cgp 2009-09-28 13:09:07

+0

您持有此信息的表格/列名称是什么? – akf 2009-09-28 13:23:05

+0

在员工... – cgp 2009-09-28 13:58:05

添加的所有相关列到你的组恭喜,你已经学会了足够的危险!

你真正想要的是每个员工最大的销售。现在恰巧按销售额desc对它们进行排序,然后将它们分组到MySQL中,尽管根据ANSI SQL这是不合法的。 (基本上,MySQL是任意抓住每个员工的第一排,并且因为排序而“有效”。)

正确的做法不是依靠排序的效果想;相反,你应该明确地询问你想要的:每个员工的最大销售额。在SQL这就是:

select employee.id, max(sale.total) 
from employee, sale 
where employee.id = sale.employee_id 
group by employee.id 
order by 2 

如果要选择具有最高销售员工,你不需要GROUP BY这里都没有。

所有你需要的是选择最高的销售,并加入它回到employees

SELECT * 
FROM (
     SELECT sale.*, ROW_NUMBER() OVER (ORDER BY total DESC) AS rn 
     FROM sale 
     ) s 
JOIN employee e 
ON  e.id = s.employee_id 
     AND s.rn = 1 

这将选择总销售最高的单排。

如果你想选择每名员工的最高销售,只需添加一个PARTITION BY子句查询:

SELECT * 
FROM (
     SELECT sale.*, ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY total DESC) AS rn 
     FROM sale 
     ) s 
JOIN employee e 
ON  e.id = s.employee_id 
     AND s.rn = 1