Groupby分组后排序,组内过滤
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
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则跳过
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 | 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','Step2',to_date('20070202','yyyy-mm-dd'));
insert into LEAD_TABLE values('Case2','Step3',to_date('20070203','yyyy-mm-dd'));
commit;
groupby分组结果如下:
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
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论