Oracle分析函數-統計(sum、avg、max、min)

不少需求中都涉及到統計:均值、累計、範圍均值、相鄰記錄比較等。這些操做會統計屢次,或有明確的統計範圍,或返回的記錄統計的數據集不一樣...函數

根據場景不一樣可分爲以下幾類:
1. 全統計
2. 滾動統計
3. 範圍統計
4. (相鄰)行比較測試

構建測試數據:spa

SQL> desc criss_sales;
Name       Type        Nullable Default Comments 
---------- ----------- -------- ------- -------- 
DEPT_ID    VARCHAR2(6) Y                         
SALE_DATE  DATE        Y                         
GOODS_TYPE VARCHAR2(4) Y                         
SALE_CNT   NUMBER(10)  Y 


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

一.全統計
最經常使用的全統計就是均值或求和,有時會要求同一行記錄包含不一樣範圍的全統計。
例:
爲數據集統計部門銷售總和,全公司銷售總和,部門銷售均值,全公司銷售均值3d

select
      dept_id
     ,sale_date
     ,goods_type
     ,sale_cnt
     ,sum(sale_cnt) over (partition by dept_id) dept_total
     ,sum(sale_cnt) over() cmp_total
     ,avg(sale_cnt) over (partition by dept_id) avg_dept
     ,avg(sale_cnt) over() avg_cmp
from criss_sales;

這樣在同一行記錄,就獲得了部門範圍的全統計(均值/求和)和公司範圍的全統計(均值/求和)。code

二.滾動統計
滾動統計最經常使用的一個場景之一是累計。blog

例:
計算部門和全公司的銷售樹量累計值。排序

select
      dept_id
     ,sale_date
     ,goods_type
     ,sale_cnt
     ,sum(sale_cnt) over(partition by dept_id order by dept_id,sale_date rows between unbounded preceding and current row) dept_cur_total
     ,sum(sale_cnt) over(order by dept_id,sale_date rows between unbounded preceding and current row) cmp_cur_total
from criss_sales;

固然,滾動查詢也能夠計算當前平均值~這裏就不在贅述了it

三.範圍統計
有時候,咱們每每關注必定範圍內的數據,例如時間範圍(一週內的數據),記錄範圍(前三條記錄到當前記錄)。io

例:按日期排序,求相相鄰三次銷售記錄的和class

select
      dept_id
     ,sale_date
     ,goods_type
     ,sale_cnt
     ,sum(sale_cnt) over(order by sale_date rows between 1 preceding and 1 following) CON_1_CNT
from criss_sales;

時間範圍例子:
按日期排序,求當前記錄日期前三天到後天三的銷售數量和

select
      dept_id
     ,sale_date
     ,goods_type
     ,sale_cnt
     ,sum(sale_cnt) over(order by sale_date range between interval '3' day preceding and interval '3' day following) sum_7_days
from criss_sales;

四.(相鄰)行比較
其實用over(order by xxx rows between 1 preceding and 0 following)也能實現相鄰行的對比。
可是,Oracle提供更方便的兩個函數 
lead() 與後面某一行對比
lag()  與前面一行對比


按時間排序,顯示當前記錄的數量以及先後相鄰記錄的銷售數量

select
      dept_id
     ,sale_date
     ,goods_type
     ,sale_cnt
     ,lag(sale_cnt,1) over(order by sale_date) lag_1
     ,lead(sale_cnt,1) over(order by sale_date) lead_1
     ,first_value(sale_cnt) over(order by sale_date rows between 1 preceding and 0 following)
from criss_sales;

最後一列是利用over(order by xxx rows between 1 preceding and 0 following)與 lag作對比。一樣能夠獲得咱們但願看到的結果。

相關文章
相關標籤/搜索