用于识别“最佳表现者”的SQL查询[?]

时间:2013-02-21 20:16:26

标签: sql oracle11g

我还在学习Oracle SQL,希望得到你的指导。

假设我们有MONTHLY_SALES_TOTALS表,其中包含3个字段:nameregionamount。我们需要确定每个地区的最佳销售人员。最好意味着它们的数量等于该地区的最大值。

CREATE TABLE montly_sales_totals
(
 name varchar(20), 
 amount numeric(9), 
 region varchar(30)
);

INSERT ALL
 INTO montly_sales_totals (name, amount, region) VALUES ('Peter', 55555,  'east')
 INTO montly_sales_totals (name, amount, region) VALUES ('Susan', 55555, 'east')
 INTO montly_sales_totals (name, amount, region) VALUES ('Mark', 1000000, 'south')
 INTO montly_sales_totals (name, amount, region) VALUES ('Glenn', 50000, 'east')
 INTO montly_sales_totals (name, amount, region) VALUES ('Paul', 500000, 'south')
SELECT * from dual;

可能的解决方案:

SELECT m1.name, m1.region, m1.amount 
FROM montly_sales_totals m1
JOIN 
 (SELECT MAX(amount) max_amount, region FROM montly_sales_totals GROUP BY region) m2
 ON (m1.region = m2.region)
WHERE m1.amount = m2.max_amount
ORDER by 2,1;

SQL小提琴http://sqlfiddle.com/#!4/6a2d8/6

现在我的问题:

  1. 此类查询效率如何?
  2. 如何/应该简化和/或改进?
  3. 我无法使用 Top ,因为“max”行的数量因地区而异。这是我可以使用的另一种直接功能吗?

4 个答案:

答案 0 :(得分:5)

我会使用RANK():

SELECT * 
FROM (
   SELECT name, amount, region,
       RANK() OVER (PARTITION BY region ORDER BY amount DESC) rnk
   FROM montly_sales_totals
  ) t
WHERE t.rnk = 1

以下是SQL Fiddle

的修改版本

答案 1 :(得分:1)

有很多方法可以解决这个问题。这是另一个:

       select S.region, S.name, V.regionmax
       from sales as S
       inner join
       (
        select region, max(amount) as regionmax
       from sales group by region 
       ) as V
       on S.region = V.region and S.amount = regionmax

关于效率,主要因素是使用适当的指数。内联视图可以很好地运行。

答案 2 :(得分:1)

我喜欢CTE语法,但是使用该网站所花的时间是2毫秒,所以我不能打败你的:)

with Maximums as (
  SELECT region,
    MAX(amount) max_amount
  FROM montly_sales_totals GROUP BY region
)
SELECT m1.name, m1.region, m1.amount 
FROM montly_sales_totals m1, Maximums 
WHERE (m1.amount = Maximums.max_amount)
  and (m1.region = Maximums.region)
ORDER by 2,1;

答案 3 :(得分:0)

你也可以通过使用这个功能......

select * from (select m1.*, row_number( ) over (partition by m1.region order by m1.amount desc,m1.name  desc ) max_sal from montly_sales_totals m1 ) where max_sal =1 ;

如果两个员工sal相同,这个查询可以做一件额外的事情!