Oracle分析函数KEEP、DENSE_RANK的使用

SELECT DECODE(ORG.ORG_NAME, '', '合计', ORG.ORG_NAME) 地市局,
       B.CREATE_COUNT 总数
  FROM (SELECT A.ORGANIZATION_ID,
               COUNT(1) CREATE_COUNT
          FROM (SELECT F.CREATE_TIME,
                       (SELECT max(ORG.ORG_ID) keep(dense_rank first order by DECODE(ORG.ORG_TYPE, 4, 1))
                          FROM TOP_ORGANIZATION ORG
                         START WITH ORG.ORG_ID = FR.ORGANIZATION_ID
                        CONNECT BY ORG.ORG_ID = PRIOR ORG.PARENT_ORG_ID) ORGANIZATION_ID,
                       F.TASK_STATUS_DESCRIBE
                  FROM SP_PD_FAULT_REPORT FR, SP_PD_FAULT F
                 WHERE F.CREATE_TIME BETWEEN
                       TO_DATE('2017-04-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
                       TO_DATE('2017-05-31 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
                   AND F.ID = FR.FAULT_ID) A
         GROUP BY ROLLUP(A.ORGANIZATION_ID)) B,
       TOP_ORGANIZATION ORG
 WHERE B.ORGANIZATION_ID = ORG.ORG_ID(+)
   AND lnnvl(ORG.ORG_TYPE != 4)
 ORDER BY ORG.SORT_NO ASC;


Sql代码   收藏代码
  1. -- emp表的数据  
  2. SQL> SELECT t.empno,  
  3.   2         t.ename,  
  4.   3         t.mgr,  
  5.   4         t.sal,  
  6.   5         t.deptno  
  7.   6    FROM emp t  
  8.   7   ORDER BY t.sal,  
  9.   8            t.deptno;  
  10.   
  11.      EMPNO ENAME                       MGR        SAL     DEPTNO  
  12. ---------- -------------------- ---------- ---------- ----------  
  13.        111 aaa                        2222        800          9  
  14.       7369 SMITH                      7902        800         20  
  15.       7900 JAMES                      7698        950         30  
  16.       7876 ADAMS                      7788       1100         20  
  17.       7521 WARD                       7698       1250         30  
  18.       7654 MARTIN                     7698       1250         30  
  19.       7934 MILLER                     7782       1300         10  
  20.       7844 TURNER                     7698       1500         30  
  21.       7499 ALLEN                      7698       1600         30  
  22.       7782 CLARK                      7839       2450         10  
  23.       7698 BLAKE                      7839       2850         30  
  24.   
  25.      EMPNO ENAME                       MGR        SAL     DEPTNO  
  26. ---------- -------------------- ---------- ---------- ----------  
  27.       7566 JONES                      7839       2975         20  
  28.       7788 SCOTT                      7566       3000         20  
  29.       7902 FORD                       7566       3000         20  
  30.       7839 KING                                  5000         10  
  31.        222 bbb                        3333       5000         40  
  32.   
  33. -- 1.现在要查询表中工资最高的部门号的最大最小值,工资最低的部门号的最大最小值  
  34. -- 因为是DENSE_RANK,会产生重复数据,使用min,max取一条。  
  35. -- 这个sql没有使用over子句,后面的例子会使用  
  36. SQL> SELECT MIN(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) a,  
  37.   2         MAX(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) b,  
  38.   3         MIN(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) c,  
  39.   4         MAX(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) d  
  40.   5    FROM emp t;  
  41.   
  42.          A          B          C          D  
  43. ---------- ---------- ---------- ----------  
  44.          9         20         10         40  
  45.   
  46. -- 2.加上over,对每一行记录做计算,看看效果:  
  47. SQL>   
  48. SQL> SELECT t.empno,  
  49.   2         t.ename,  
  50.   3         t.mgr,  
  51.   4         t.sal,  
  52.   5         t.deptno,  
  53.   6         MIN(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) OVER() a,  
  54.   7         MAX(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) OVER() b,  
  55.   8         MIN(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) OVER() c,  
  56.   9         MAX(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) OVER() d  
  57.  10    FROM emp t  
  58.  11   ORDER BY t.sal,  
  59.  12            t.deptno  
  60.  13  ;  
  61.   
  62. EMPNO ENAME        MGR       SAL DEPTNO          A          B          C          D  
  63. ----- ---------- ----- --------- ------ ---------- ---------- ---------- ----------  
  64.   111 aaa         2222    800.00      9          9         20         10         40  
  65.  7369 SMITH       7902    800.00     20          9         20         10         40  
  66.  7900 JAMES       7698    950.00     30          9         20         10         40  
  67.  7876 ADAMS       7788   1100.00     20          9         20         10         40  
  68.  7521 WARD        7698   1250.00     30          9         20         10         40  
  69.  7654 MARTIN      7698   1250.00     30          9         20         10         40  
  70.  7934 MILLER      7782   1300.00     10          9         20         10         40  
  71.  7844 TURNER      7698   1500.00     30          9         20         10         40  
  72.  7499 ALLEN       7698   1600.00     30          9         20         10         40  
  73.  7782 CLARK       7839   2450.00     10          9         20         10         40  
  74.  7698 BLAKE       7839   2850.00     30          9         20         10         40  
  75.  7566 JONES       7839   2975.00     20          9         20         10         40  
  76.  7788 SCOTT       7566   3000.00     20          9         20         10         40  
  77.  7902 FORD        7566   3000.00     20          9         20         10         40  
  78.  7839 KING               5000.00     10          9         20         10         40  
  79.   222 bbb         3333   5000.00     40          9         20         10         40  
  80.   
  81. -- 3.下面对每一个mgr求最大(最小)工资的部门号的最大(最小)值  
  82. SQL> SELECT t.empno,  
  83.   2         t.ename,  
  84.   3         t.mgr,  
  85.   4         t.sal,  
  86.   5         t.deptno,  
  87.   6         MIN(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) OVER(PARTITION BY t.mgr) a,  
  88.   7         MAX(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) OVER(PARTITION BY t.mgr) b,  
  89.   8         MIN(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) OVER(PARTITION BY t.mgr) c,  
  90.   9         MAX(t.deptno) KEEP(DENSE_RANK LAST ORDER BY t.sal) OVER(PARTITION BY t.mgr) d  
  91.  10    FROM emp t  
  92.  11   ORDER BY t.sal,  
  93.  12            t.deptno  
  94.  13  ;  
  95.   
  96. EMPNO ENAME        MGR       SAL DEPTNO          A          B          C          D  
  97. ----- ---------- ----- --------- ------ ---------- ---------- ---------- ----------  
  98.   111 aaa         2222    800.00      9          9          9          9          9  
  99.  7369 SMITH       7902    800.00     20         20         20         20         20  
  100.  7900 JAMES       7698    950.00     30         30         30         30         30  
  101.  7876 ADAMS       7788   1100.00     20         20         20         20         20  
  102.  7654 MARTIN      7698   1250.00     30         30         30         30         30  
  103.  7521 WARD        7698   1250.00     30         30         30         30         30  
  104.  7934 MILLER      7782   1300.00     10         10         10         10         10  
  105.  7844 TURNER      7698   1500.00     30         30         30         30         30  
  106.  7499 ALLEN       7698   1600.00     30         30         30         30         30  
  107.  7782 CLARK       7839   2450.00     10         10         10         20         20  
  108.  7698 BLAKE       7839   2850.00     30         10         10         20         20  
  109.  7566 JONES       7839   2975.00     20         10         10         20         20  
  110.  7902 FORD        7566   3000.00     20         20         20         20         20  
  111.  7788 SCOTT       7566   3000.00     20         20         20         20         20  
  112.  7839 KING               5000.00     10         10         10         10         10  
  113.   222 bbb         3333   5000.00     40         40         40         40         40  



最近在工作中,碰到一个问题,后来在处理过程中接触到了KEEP,DENSE_RANK分析函数,问题瞬间被简单的解决,否则按照常规写法,肯定会写出嵌套语句,但是网上对这个方面的介绍比较少,现在特整理了一下:

从目前查到的来看:DENSE_RANK是和KEEP结合使用的,网上给出的解释是Returns the row ranked first using DENSE_RANK。我的理解是返回DENSE_RANK函数的第一结果。一般写法是 MIN [ MAX ] (A) KEEP(DENSE_RANK FIRST [ LAST ] ORDER BY B),这里引用别人说的明的解释一下:

DENSE_RANK

功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。密集的序列返回的时没有间隔的数。

FIRST

功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

LAST
功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

所以默认排序下,FIRST可以理解是取小值,LAST取大值。而前面的MIN或者MAX则是在KEEP的结果集中取某一字段的最大值或最小值。
语文没学好 可怜上面的可能没说清楚,而且网上的相关的资料也少,所以最后给大家看一个完整的SQL语句并解释一下作用,大家自己理解一下吧....

[sql]  view plain  copy
  1. SELECT ZGH,  
  2.        MIN(WM) KEEP(DENSE_RANK FIRST ORDER BY WM),  
  3.        MIN(RQ) KEEP(DENSE_RANK FIRST ORDER BY WM)  
  4.   FROM T_JZG  
  5.  GROUP BY ZGH  
表结构大概如下:
ZGHWMRQ
A120130101
A220140102
A120120102
B320131001
B220140102
B320121004

其中相同ZGH对应的字段WM、RQ值可能有多条,要求从中取出WM值最小的那一条,但可能存在多条,这时要取出其中RQ最小的那一条,以上语句可以实现。
最后取出的值应该是:
ZGHWMRQ
A120120102
B220140102

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值