4

我仍在学习 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,因为“最大”行数因地区而异。它是我可以使用的另一个直接功能吗?
4

4 回答 4

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的修改版本

于 2013-02-21T20:18:42.887 回答
1

There are a number of ways one can go about this. Here's another:

       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

As to efficiency, the main factor is the use of the proper index(es). Inline views can perform very well.

于 2013-02-21T20:40:13.190 回答
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;
于 2013-02-21T21:25:32.850 回答
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 相同,则此查询可以做一件额外的事情!

于 2013-02-22T14:26:02.283 回答