ITPub博客

首页 > 数据库 > Oracle > 分析函数概述

分析函数概述

原创 Oracle 作者:呆呆笨笨的鱼 时间:2014-06-06 13:12:42 0 删除 编辑
先通过一个例子,直观的感受下分析函数的简洁方便

构造数据:
销售表:
create table CRISS_SALES
(
  DEPT_ID    VARCHAR2(6),    --部门号
  SALE_DATE  DATE,           --销售日期
  GOODS_TYPE VARCHAR2(4),    --货物类型
  SALE_CNT   NUMBER(10)      --销售数量
);

insert into CRISS_SALES values ('D01', TO_DATE('20140304', 'YYYYMMDD'), 'G00', 700);
insert into CRISS_SALES values ('D02', TO_DATE('20140306', 'YYYYMMDD'), 'G00', 500);
insert into CRISS_SALES values ('D01', TO_DATE('20140408', 'YYYYMMDD'), 'G01', 200);
insert into CRISS_SALES values ('D02', TO_DATE('20140427', 'YYYYMMDD'), 'G01', 300);
insert into CRISS_SALES values ('D01', TO_DATE('20140430', 'YYYYMMDD'), 'G03', 800);
insert into CRISS_SALES values ('D02', TO_DATE('20140502', 'YYYYMMDD'), 'G03', 900);
insert into CRISS_SALES values ('D01', TO_DATE('20140504', 'YYYYMMDD'), 'G02', 80);
insert into CRISS_SALES values ('D02', TO_DATE('20140408', 'YYYYMMDD'), 'G02', 100);


SQL> select *from criss_sales order by sale_date;
 
DEPT_ID SALE_DATE   GOODS_TYPE    SALE_CNT
------- ----------- ---------- -----------
D01     2014/3/4    G00                700
D02     2014/3/6    G00                500
D01     2014/4/8    G01                200
D02     2014/4/8    G02                100
D02     2014/4/27   G01                300
D01     2014/4/30   G03                800
D02     2014/5/2    G03                900
D01     2014/5/4    G02                 80

求出全公每个时点司累计的销售数量

即:希望得到的结果为如下形式: 
DEPT_ID SALE_DATE   GOODS_TYPE    SALE_CNT   ALL_CMP_CNT
------- ----------- ---------- ----------- --------------
D01     2014/3/4    G00                700      700
D02     2014/3/6    G00                500     1200
           .........
D02     2014/5/2    G03                900     3500
D01     2014/5/4    G02                 80     3580


先不用分析函数解决这个问题
利用伪列
with t as 
(
select 
  DEPT_ID
 ,SALE_DATE
 ,GOODS_TYPE
 ,SALE_CNT
 ,rownum rn
from (select 
  DEPT_ID
 ,SALE_DATE
 ,GOODS_TYPE
 ,SALE_CNT
from criss_sales
order by sale_date
)tmp
) 
select 
  a.DEPT_ID
 ,a.SALE_DATE
 ,a.GOODS_TYPE
 ,a.SALE_CNT
 ,sum(b.SALE_CNT) ALL_CMP_CNT
from t a
left join t b
on (a.rn + 1 > b.rn  )
group by
  a.DEPT_ID
 ,a.SALE_DATE
 ,a.GOODS_TYPE
 ,a.SALE_CNT
order by SALE_DATE
;


DEPT_ID SALE_DATE   GOODS_TYPE    SALE_CNT ALL_CMP_CNT
------- ----------- ---------- ----------- -----------
D01     2014/3/4    G00                700         700
D02     2014/3/6    G00                500        1200
D01     2014/4/8    G01                200        1400
D02     2014/4/8    G02                100        1500
D02     2014/4/27   G01                300        1800
D01     2014/4/30   G03                800        2600
D02     2014/5/2    G03                900        3500
D01     2014/5/4    G02                 80        3580


利用分析函数
select 
  DEPT_ID
 ,SALE_DATE
 ,GOODS_TYPE
 ,sum(SALE_CNT) over(order by SALE_DATE rows between unbounded preceding and current row) ALL_CMP_CNT
from criss_sales
;

DEPT_ID SALE_DATE   GOODS_TYPE    SALE_CNT ALL_CMP_CNT
------- ----------- ---------- ----------- -----------
D01     2014/3/4    G00                700         700
D02     2014/3/6    G00                500        1200
D01     2014/4/8    G01                200        1400
D02     2014/4/8    G02                100        1500
D02     2014/4/27   G01                300        1800
D01     2014/4/30   G03                800        2600
D02     2014/5/2    G03                900        3500
D01     2014/5/4    G02                 80        3580


通过这个例子,可以看到利用分析函数解决某些场景下的问题非常的直观简便。

分析函数适用于哪些场景?
1.表内数据聚合累加
2.表内分组累加
3.分组排名
4.滚动统计
5.范围求值SUM MAX MIN
6.相邻行比较
等等...


Oracle提供的分析函数有哪些?
==================================================
统计方面:
Sum() Over ([Partition by ] [Order by ]) --统计全表

--统计前n行到后m行
Sum() Over ([Partition by ] [Order by ]  
     Rows Between n Preceding And m Following)

--统计前n行到当前行      
Sum() Over ([Partition by ] [Order by ]
     Rows Between n Preceding And Current Row)

--统计开始行到当前行
Sum() Over ([Partition by ] [Order by ]
     Rows Between unbounded Preceding And Current Row)

--统计开始行到当前行之后的第n行     
Sum() Over ([Partition by ] [Order by ]
     Rows Between unbounded Preceding n Following)
     
前面的例子就使用了
Sum() Over ([Partition by ] [Order by ]
     Rows Between unbounded Preceding And Current Row)
其他的有兴趣可以自行实验下结果

===================================================
有关排列或排名:
--非连续排名
Rank() Over ([Partition by ] [Order by ] [Nulls First/Last])

--连续排名
Dense_rank() Over ([Patition by ] [Order by ] [Nulls First/Last])

--排序行号
Row_number() Over ([Partitionby ] [Order by ] [Nulls First/Last])
   
Ntile() Over ([Partition by ] [Order by ])


create table s_score
( s_id number(6)
 ,score number(4,2)
);
insert into s_score values(001,98);
insert into s_score values(002,66.5);
insert into s_score values(003,99);
insert into s_score values(004,98);
insert into s_score values(005,98);
insert into s_score values(006,80);

select
    s_id 
   ,score
   ,rank() over(order by score desc) rank
   ,dense_rank() over(order by score desc) dense_rank
   ,row_number() over(order by score desc) row_number
from s_score;

   S_ID  SCORE       RANK DENSE_RANK ROW_NUMBER
------- ------ ---------- ---------- ----------
      3  99.00          1          1          1
      1  98.00          2          2          2
      4  98.00          2          2          3
      5  98.00          2          2          4
      6  80.00          5          3          5
      2  66.50          6          4          6
      

==========================================================
最大值/最小值查找:
Min()/Max() Keep (Dense_rank First/Last [Partition by ] [Order by ])

==========================================================
首记录/末记录查找:
First_value / Last_value(Sum() Over ([Patition by ] [Order by ]
       Rows Between  Preceding And  Following  ))
       
==========================================================
相邻记录之间比较 lead/lag:
Lag(Sum(), 1) Over([Patition by ] [Order by ])

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28929558/viewspace-1176900/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-04-17

  • 博文量
    62
  • 访问量
    939480