不少需求中都涉及到統計:均值、累計、範圍均值、相鄰記錄比較等。這些操做會統計屢次,或有明確的統計範圍,或返回的記錄統計的數據集不一樣...函數
根據場景不一樣可分爲以下幾類:
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作對比。一樣能夠獲得咱們但願看到的結果。