小编典典

Oracle Analytic函数可实现分组中的最小值

sql

我是分析功能的新手。

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  10 JOHN  200000
  10 SCOTT 300000
  20 BOB   100000
  20 BETTY 200000
  30 ALAN  100000
  30 TOM   200000
  30 JEFF  300000

我要最低工资的部门和雇员。

结果应如下所示:

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  20 BOB   100000
  30 ALAN  100000

编辑:这是我有的SQL(但当然,它不起作用,因为它也希望group by子句中的人员):

SELECT dept, 
  emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary)
FROM mytable

阅读 251

收藏
2021-03-23

共1个答案

小编典典

我认为Rank()函数不是解决这个问题的方法,这有两个原因。

首先,它可能不如基于Min()的方法有效。

原因是查询在扫描数据时必须维护每个部门所有薪水的有序列表,然后稍后将通过重新读取此列表来分配等级。显然,在没有可用于此目的的索引的情况下,在读取完最后一个数据项之前,您无法分配等级,并且维护列表的成本很高。

因此,Rank()函数的性能取决于要扫描的元素总数,如果数量足以使排序溢出到磁盘,则性能将下降。

这可能更有效:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

此方法仅要求查询在每个部门中维护到目前为止所遇到的最小值的单个值。如果遇到新的最小值,则将修改现有值,否则将丢弃新值。必须保留在内存中的元素总数与部门数有关,而不与扫描的行数有关。

可能是甲骨文拥有一条代码路径来识别在这种情况下并不需要真正计算排名,但是我不会打赌。

不喜欢Rank()的第二个原因是它只是回答了错误的问题。问题不是“哪个记录的薪水是每个部门的薪水递增时的第一位”,而是“哪个记录的薪水是每个部门的最低薪水”。至少对我来说,那有很大的不同。

2021-03-23