Oracle 分析彙總函數--報表

原文鏈接:https://www.cnblogs.com/sooner/p/7727637.html

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

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

構建測試數據:

複製代碼

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

複製代碼


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

複製代碼

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;

複製代碼

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


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

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

複製代碼

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;

複製代碼

當然,滾動查詢也可以計算當前平均值~這裏就不在贅述了


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

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

複製代碼

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做對比。同樣可以得到我們希望看到的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章