Oracle分析函数KEEP、DENSE_RANK的使用

前端之家收集整理的这篇文章主要介绍了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;


  1. --emp表的数据
  2. sql>SELECTt.empno,
  3. 2t.ename,250)"> 3t.mgr,250)"> 4t.sal,250)"> 5t.deptno
  4. 6FROMempt
  5. 7ORDERBYt.sal,250)"> 8t.deptno;
  6. EMPNOENAMEMGRSALDEPTNO
  7. ------------------------------------------------------------
  8. 111aaa22228009
  9. 7369SMITH790280020
  10. 7900JAMES769895030
  11. 7876ADAMS7788110020
  12. 7521WARD7698125030
  13. 7654MARTIN7698125030
  14. 7934MILLER7782130010
  15. 7844TURNER7698150030
  16. 7499ALLEN7698160030
  17. 7782CLARK7839245010
  18. 7698BLAKE7839285030
  19. 7566JONES7839297520
  20. 7788SCOTT7566300020
  21. 7902FORD7566300020
  22. 7839KING500010
  23. 222bbb3333500040
  24. --1.现在要查询表中工资最高的部门号的最大最小值,工资最低的部门号的最大最小值
  25. --因为是DENSE_RANK,会产生重复数据,使用min,max取一条。
  26. --这个sql没有使用over子句,后面的例子会使用
  27. SELECTMIN(t.deptno)KEEP(DENSE_RANKFIRSTBYt.sal)a,250)"> 2MAX(t.deptno)KEEP(DENSE_RANKBYt.sal)b,250)"> 3LASTBYt.sal)c,250)"> 4BYt.sal)d
  28. 5FROMempt;
  29. ABCD
  30. ----------------------------------------
  31. 9201040
  32. --2.加上over,对每一行记录做计算,看看效果
  33. sql>
  34. 5t.deptno,85); font-weight:bold">BYt.sal)OVER()a,85); font-weight:bold">BYt.sal)OVER()b,250)"> 8BYt.sal)OVER()c,250)"> 9BYt.sal)OVER()d
  35. 10 11 12t.deptno
  36. 13;
  37. EMPNOENAMEMGRSALDEPTNOABCD
  38. ---------------------------------------------------------------------------
  39. 111aaa2222800.0099201040
  40. 7369SMITH7902800.00209201040
  41. 7900JAMES7698950.00309201040
  42. 7876ADAMS77881100.00209201040
  43. 7521WARD76981250.00309201040
  44. 7654MARTIN76981250.00309201040
  45. 7934MILLER77821300.00109201040
  46. 7844TURNER76981500.00309201040
  47. 7499ALLEN76981600.00309201040
  48. 7782CLARK78392450.00109201040
  49. 7698BLAKE78392850.00309201040
  50. 7566JONES78392975.00209201040
  51. 7788SCOTT75663000.00209201040
  52. 7902FORD75663000.00209201040
  53. 7839KING5000.00109201040
  54. 222bbb33335000.00409201040
  55. --3.下面对每一个mgr求最大(最小)工资的部门号的最大(最小)值
  56. BYt.sal)OVER(PARTITIONBYt.mgr)a,85); font-weight:bold">BYt.mgr)b,85); font-weight:bold">BYt.mgr)c,85); font-weight:bold">BYt.mgr)d
  57. 111aaa2222800.0099999
  58. 7369SMITH7902800.002020202020
  59. 7900JAMES7698950.003030303030
  60. 7876ADAMS77881100.002020202020
  61. 7654MARTIN76981250.003030303030
  62. 7521WARD76981250.003030303030
  63. 7934MILLER77821300.001010101010
  64. 7844TURNER76981500.003030303030
  65. 7499ALLEN76981600.003030303030
  66. 7782CLARK78392450.001010102020
  67. 7698BLAKE78392850.003010102020
  68. 7566JONES78392975.002010102020
  69. 7902FORD75663000.002020202020
  70. 7788SCOTT75663000.002020202020
  71. 7839KING5000.001010101010
  72. 222bbb33335000.004040404040



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

从目前查到的来看:DENSE_RANK是和KEEP结合使用的,网上给出的解释是Returns the row rankedfirstusing 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 @H_356_403@
  1. SELECTZGH,
  2. MIN(WM)KEEP(DENSE_RANKFIRSTORDERBYWM),
  3. MIN(RQ)KEEP(DENSE_RANKBYWM)
  4. FROMT_JZG
  5. GROUPBYZGH
表结构大概如下:
ZGH WM RQ
A 1 20130101
A 2 20140102
A 1 20120102
B 3 20131001
B 2 20140102
B 3 20121004

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


猜你在找的Oracle相关文章