IT忍者神龟之oracle 在分组内排序的方法回顾
oracle分析函数十分强大,我们只要掌握这些方法,更直接的说法就是知道这些分析函数的作用就能完成很多工作。
下边贴出这些函数,及简单应用。
其中我想对lag()和lead()函数坐下说明:lag()本身是延后的意思也就是延后出现某列的数,而lead()有引领、领先的意思也就是提前几行显示某列数据
RANK() dense_rank() 【语法】RANK ( ) OVER ( [query_partition_clause] order_by_clause ) dense_RANK ( ) OVER ( [query_partition_clause] order_by_clause ) 【功能】聚合函数RANK 和 dense_rank 主要的功能是计算一组数值中的排序值。 【参数】dense_rank与rank()用法相当, 【区别】dence_rank在并列关系是,相关等级不会跳过。rank则跳过 rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内) dense_rank()l是连续排序,有两个第二名时仍然跟着第三名。 【说明】Oracle分析函数 【示例】 聚合函数RANK 和 dense_rank 主要的功能是计算一组数值中的排序值。 在9i版本之前,只有分析功能(analytic ),即从一个查询结果中计算每一行的排序值,是基于order_by_clause子句中的value_exprs指定字段的。 其语法为: RANK ( ) OVER ( [query_partition_clause] order_by_clause ) 在9i版本新增加了合计功能(aggregate),即对给定的参数值在设定的排序查询中计算出其排序值。这些参数必须是常数或常值表达式,且必须和ORDER BY子句中的字段个数、位置、类型完全一致。 其语法为: RANK ( expr [, expr]... ) WITHIN GROUP ( ORDER BY expr [ DESC | ASC ] [NULLS { FIRST | LAST }] [, expr [ DESC | ASC ] [NULLS { FIRST | LAST }]]... ) 例子1: 有表Table内容如下 COL1 COL2 1 1 2 1 3 2 3 1 4 1 4 2 5 2 5 2 6 2 分析功能:列出Col2分组后根据Col1排序,并生成数字列。比较实用于在成绩表中查出各科前几名的信息。 SELECT a.*,RANK() OVER(PARTITION BY col2 ORDER BY col1) "Rank" FROM table a; 结果如下: COL1 COL2 Rank 1 1 1 2 1 2 3 1 3 4 1 4 3 2 1 4 2 2 5 2 3 5 2 3 6 2 5 例子2: TABLE:A (科目,分数) 数学,80 语文,70 数学,90 数学,60 数学,100 语文,88 语文,65 语文,77 现在我想要的结果是:(即想要每门科目的前3名的分数) 数学,100 数学,90 数学,80 语文,88 语文,77 语文,70 那么语句就这么写: select * from (select rank() over(partition by 科目 order by 分数 desc) rk,a.* from a) t where t.rk<=3; 例子3: 合计功能:计算出数值(4,1)在Orade By Col1,Col2排序下的排序值,也就是col1=4,col2=1在排序以后的位置 SELECT RANK(4,3) WITHIN GROUP (ORDER BY col1,col2) "Rank" FROM table; 结果如下: Rank 4 dense_rank与rank()用法相当,但是有一个区别:dence_rank在并列关系是,相关等级不会跳过。rank则跳过 例如:表 A B C a liu wang a jin shu a cai kai b yang du b lin ying b yao cai b yang 99 例如:当rank时为: select m.a,m.b,m.c,rank() over(partition by a order by b) liu from test3 m A B C LIU a cai kai 1 a jin shu 2 a liu wang 3 b lin ying 1 b yang du 2 b yang 99 2 b yao cai 4 而如果用dense_rank时为: select m.a,m.b,m.c,dense_rank() over(partition by a order by b) liu from test3 m A B C LIU a cai kai 1 a jin shu 2 a liu wang 3 b lin ying 1 b yang du 2 b yang 99 2 b yao cai 3
ROW_NUMBER() 【语法】ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2) 【功能】表示根据COL1分组,在分组内部根据 COL2排序,而这个值就表示每组内部排序后的顺序编号(组内连续的唯一的) row_number() 返回的主要是“行”的信息,并没有排名 【参数】 【说明】Oracle分析函数 主要功能:用于取前几名,或者最后几名等 【示例】 表内容如下: name | seqno | description A | 1 | test A | 2 | test A | 3 | test A | 4 | test B | 1 | test B | 2 | test B | 3 | test B | 4 | test C | 1 | test C | 2 | test C | 3 | test C | 4 | test 我想有一个sql语句,搜索的结果是 A | 1 | test A | 2 | test B | 1 | test B | 2 | test C | 1 | test C | 2 | test 实现: select name,seqno,description from(select name,seqno,description,row_number() over (partition by name order by seqno) id from table_name) where id<=3;lag()和lead() 【语法】 lag(EXPR,<OFFSET>,<DEFAULT>) LEAD(EXPR,<OFFSET>,<DEFAULT>) 【功能】表示根据COL1分组,在分组内部根据 COL2排序,而这个值就表示每组内部排序后的顺序编号(组内连续的唯一的) lead () 下一个值 lag() 上一个值 【参数】 EXPR是从其他行返回的表达式 OFFSET是缺省为1 的正数,表示相对行数。希望检索的当前行分区的偏移量 DEFAULT是在OFFSET表示的数目超出了分组的范围时返回的值。 【说明】Oracle分析函数 【示例】 -- Create table create table LEAD_TABLE ( CASEID VARCHAR2(10), STEPID VARCHAR2(10), ACTIONDATE DATE ) tablespace COLM_DATA pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited ); insert into LEAD_TABLE values(‘Case1‘,‘Step1‘,to_date(‘20070101‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step2‘,to_date(‘20070102‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step3‘,to_date(‘20070103‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step4‘,to_date(‘20070104‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step5‘,to_date(‘20070105‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step4‘,to_date(‘20070106‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step6‘,to_date(‘20070101‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case1‘,‘Step1‘,to_date(‘20070201‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case2‘,‘Step2‘,to_date(‘20070202‘,‘yyyy-mm-dd‘)); insert into LEAD_TABLE values(‘Case2‘,‘Step3‘,to_date(‘20070203‘,‘yyyy-mm-dd‘)); commit; 结果如下: Case1 Step1 2007-1-1 Step2 2007-1-2 Case1 Step2 2007-1-2 Step3 2007-1-3 Step1 2007-1-1 Case1 Step3 2007-1-3 Step4 2007-1-4 Step2 2007-1-2 Case1 Step4 2007-1-4 Step5 2007-1-5 Step3 2007-1-3 Case1 Step5 2007-1-5 Step4 2007-1-6 Step4 2007-1-4 Case1 Step4 2007-1-6 Step6 2007-1-7 Step5 2007-1-5 Case1 Step6 2007-1-7 Step4 2007-1-6 Case2 Step1 2007-2-1 Step2 2007-2-2 Case2 Step2 2007-2-2 Step3 2007-2-3 Step1 2007-2-1 Case2 Step3 2007-2-3 Step2 2007-2-2 还可以进一步统计一下两者的相差天数 select caseid,stepid,actiondate,nextactiondate,nextactiondate-actiondate datebetween from ( select caseid,stepid,actiondate,lead(stepid) over (partition by caseid order by actiondate) nextstepid, lead(actiondate) over (partition by caseid order by actiondate) nextactiondate, lag(stepid) over (partition by caseid order by actiondate) prestepid, lag(actiondate) over (partition by caseid order by actiondate) preactiondate from lead_table) 结果如下: Case1 Step1 2007-1-1 2007-1-2 1 Case1 Step2 2007-1-2 2007-1-3 1 Case1 Step3 2007-1-3 2007-1-4 1 Case1 Step4 2007-1-4 2007-1-5 1 Case1 Step5 2007-1-5 2007-1-6 1 Case1 Step4 2007-1-6 2007-1-7 1 Case1 Step6 2007-1-7 Case2 Step1 2007-2-1 2007-2-2 1 Case2 Step2 2007-2-2 2007-2-3 1 Case2 Step3 2007-2-3 每一条记录都能连接到上/下一行的内容 lead () 下一个值 lag() 上一个值 select caseid,stepid,actiondate,lead(stepid) over (partition by caseid order by actiondate) nextstepid, lead(actiondate) over (partition by caseid order by actiondate) nextactiondate, lag(stepid) over (partition by caseid order by actiondate) prestepid, lag(actiondate) over (partition by caseid order by actiondate) preactiondate from lead_table
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。