oracle常用的分析函數

分析函數,最早是從ORACLE8.1.6開始出現的,它的設計目的是爲了解決諸如“累計計算”,“找出分組內百分比”,“前-N條查詢”,

“移動平均數計算”"等問題。其實大部分的問題都可以用PL/SQL解決,但是它的性能並不能達到你所期望的效果。分析函數是SQL

語言的一種擴充,它並不是僅僅試代碼變得更簡單而已,它的速度比純粹的SQL或者PL/SQL更快


分析函數原理:
分析函數是在一個記錄行分組的基礎上計算它們的總值,與普通集合函數不同的是,他們在各組中返回多行,行的分組被稱爲“窗口”
窗口大小表示用於統計計算的行數,窗口的大小是基於物理行數或邏輯間隔(例如時間)。


除了ORDER BY(按…排序)語句外,分析函數是一條查詢被執行的操作。所有合併、WHERE、GROUP BY、HAVING語句都是分析函數處理之前完成的。因此,分析函數只出現在select 列表或ORDER BY(按…排序)語句中。

一. 分組彙總函數rollup,cube

常規彙總方法

SQL> set timing on;
SQL> 
SQL>   select to_char(o.lottery_id),sum(o.money)
  2    from  tb_order o
  3    where o.state=4
  4    and o.buy_time>sysdate-30
  5    group by o.lottery_id
  6    union all
  7    select '合計',sum(o.money)
  8    from  tb_order o
  9    where o.state=4
 10    and o.buy_time>sysdate-30
 11  ;

TO_CHAR(O.LOTTERY_ID)                    SUM(O.MONEY)
---------------------------------------- ------------
14                                               8810
22                                                278
58                                                 78
合計                                             9166

Executed in 0.032 seconds

 

總計信息:consistent gets:412

 

使用rollup進行彙總
SQL> 
SQL>   select decode(o.lottery_id,null,'所有彩種統計',o.lottery_id),sum(o.money)
  2    from  tb_order o
  3    where o.state=4
  4    and o.buy_time>sysdate-30
  5    group by rollup(o.lottery_id)
  6  ;

DECODE(O.LOTTERY_ID,NULL,'所有           SUM(O.MONEY)
---------------------------------------- ------------
14                                               8810
22                                                278
58                                                 78
所有彩種統計                                     9166

Executed in 0.047 seconds

SQL>

總計信息:consistent gets:206

 

對比

傳統的一致讀:consistent gets:412
使用分析函數的一致讀:consistent gets:206

從對比信息可以看到,如果數據量很大的話,對比效果就更明顯

再深入的一點看看多個字段分組統計

SQL>   select decode(grouping(o.lottery_id),1,'所有彩種',o.lottery_id),
  2          decode(grouping(trunc(o.buy_time,'dd')),1,'所有天數',trunc(o.buy_time,'dd')),
  3    sum(o.money)
  4    from  tb_order o
  5    where o.state=4
  6    and   o.buy_time>sysdate-30
  7    group by rollup(o.lottery_id,trunc(o.buy_time,'dd'))
  8   
  9    order by o.lottery_id
 10  ;

DECODE(GROUPING(O.LOTTERY_ID),           DECODE(GROUPING(TRUNC(O.BUY_TI SUM(O.MONEY)
---------------------------------------- ------------------------------ ------------
14                                       08-11月-10                               96
14                                       09-11月-10                              156
14                                       10-11月-10                             8544
14                                       11-11月-10                               10
14                                       15-11月-10                                4
14                                       所有天數                               8810
22                                       09-11月-10                              278
22                                       所有天數                                278
58                                       08-11月-10                               78
58                                       所有天數                                 78
所有彩種                                 所有天數                               9166

 

11 rows selected

Executed in 0.109 seconds

SQL>

這裏的rollup(o.lottery_id,trunc(o.buy_time,'dd'))是先對o.lottery_id 進行group by ,然後再對(o.lottery_id,trunc(o.buy_time,'dd')) 進行group by,兩個字段比較好理解,那三個字段呢?

 

SQL>   select decode(grouping(o.lottery_id),1,'所有彩種',o.lottery_id) lottery_id,
  2          decode(grouping(trunc(o.buy_time,'dd')),1,'所有天數',trunc(o.buy_time,'dd')) buy_time,
  3    sum(o.money) ,decode(grouping(o.ware_id),1,'所有wareid',o.ware_id) ware_id
  4    from  tb_order o
  5    where o.state=4
  6    and   o.buy_time>sysdate-30
  7    group by rollup(o.lottery_id,trunc(o.buy_time,'dd'),o.ware_id)
  8    
  9    order by o.lottery_id,trunc(o.buy_time,'dd')
 10  ;

LOTTERY_ID                               BUY_TIME       SUM(O.MONEY) WARE_ID
---------------------------------------- -------------- ------------ ----------------------------------------
14                                       08-11月-10               96 47055
14                                       08-11月-10               96 所有wareid
14                                       09-11月-10              156 47055
14                                       09-11月-10              156 所有wareid
14                                       10-11月-10             8544 47059
14                                       10-11月-10             8544 所有wareid
14                                       11-11月-10               10 47059
14                                       11-11月-10               10 所有wareid
14                                       15-11月-10                4 47066
14                                       15-11月-10                4 所有wareid
14                                       所有天數               8810 所有wareid
22                                       09-11月-10              278 47057
22                                       09-11月-10              278 所有wareid
22                                       所有天數                278 所有wareid
58                                       08-11月-10               78 47043
58                                       08-11月-10               78 所有wareid
58                                       所有天數                 78 所有wareid
所有彩種                                 所有天數               9166 所有wareid

 

18 rows selected

Executed in 0.187 seconds

說明:
從上面的結果中我們很容易發現,如果不用decode函數,每個統計數據所對應的行都會出現null,
並且我們如何來區分到底是根據那個字段做的彙總呢?這時候,oracle的grouping函數就派上用場了.
如果當前的彙總記錄是利用該字段得出的,grouping函數就會返回1,否則返回0

這裏的rollup(o.lottery_id,trunc(o.buy_time,'dd'),o.ware_id)是先對o.lottery_id進行group by ,然後在對(o.lottery_id,trunc(o.buy_time,'dd'))進行group by,最後在對(o.lottery_id,trunc(o.buy_time,'dd'),o.ware_id)進行group by;每次的group by 都會進行數據彙總


從上面的結果我們可以看到,共有如下幾項統計彙總

1. 按(LOTTERY_ID,BUY_TIME)進行的統計彙總,即統計每個彩種每天所有的商品(wareid)銷售總額
2. 按 (LOTTERY_ID)進行彙總,即統計每個彩種在所有天裏,所有wareid的銷售總額
3. 所有彩種,在所有天裏,銷售所有的商品(wareid)的總銷售額


那我們要如何統計如下的彙總呢?,難道還要在sql(估計很複雜)或pl?sql
所有彩種,每天,每個商品(wareid)的銷售總額;
所有彩種,每天,所有商品(wareid)的銷售總額;
所有彩種,所有天裏,每個商品(wareid)的銷售總額;

其實我們可以用cube來實現,如下所示

SQL> 
SQL>  select decode(grouping(o.lottery_id),1,'所有彩種',o.lottery_id) lottery_id,
  2          decode(grouping(trunc(o.buy_time,'dd')),1,'所有天數',trunc(o.buy_time,'dd')) buy_time,
  3    sum(o.money) ,decode(grouping(o.ware_id),1,'所有wareid',o.ware_id) ware_id
  4    from  tb_order o
  5    where o.state=4
  6    and   o.buy_time>sysdate-30
  7    
  8    group by cube(o.lottery_id,trunc(o.buy_time,'dd'),o.ware_id)
  9    order by o.lottery_id,trunc(o.buy_time,'dd')
 10  ;

LOTTERY_ID                               BUY_TIME       SUM(O.MONEY) WARE_ID
---------------------------------------- -------------- ------------ ----------------------------------------
14                                       08-11月-10               96 所有wareid
14                                       08-11月-10               96 47055
14                                       09-11月-10              156 所有wareid
14                                       09-11月-10              156 47055
14                                       10-11月-10             8544 所有wareid
14                                       10-11月-10             8544 47059
14                                       11-11月-10               10 所有wareid
14                                       11-11月-10               10 47059
14                                       15-11月-10                4 所有wareid
14                                       15-11月-10                4 47066
14                                       所有天數               8810 所有wareid
14                                       所有天數                252 47055
14                                       所有天數               8554 47059
14                                       所有天數                  4 47066
22                                       09-11月-10              278 所有wareid
22                                       09-11月-10              278 47057
22                                       所有天數                278 所有wareid
22                                       所有天數                278 47057
58                                       08-11月-10               78 所有wareid
58                                       08-11月-10               78 47043

LOTTERY_ID                               BUY_TIME       SUM(O.MONEY) WARE_ID
---------------------------------------- -------------- ------------ ----------------------------------------
58                                       所有天數                 78 所有wareid
58                                       所有天數                 78 47043
所有彩種                                 08-11月-10              174 所有wareid
所有彩種                                 08-11月-10               78 47043
所有彩種                                 08-11月-10               96 47055
所有彩種                                 09-11月-10              434 所有wareid
所有彩種                                 09-11月-10              156 47055
所有彩種                                 09-11月-10              278 47057
所有彩種                                 10-11月-10             8544 所有wareid
所有彩種                                 10-11月-10             8544 47059
所有彩種                                 11-11月-10               10 所有wareid
所有彩種                                 11-11月-10               10 47059
所有彩種                                 15-11月-10                4 所有wareid
所有彩種                                 15-11月-10                4 47066
所有彩種                                 所有天數               9166 所有wareid
所有彩種                                 所有天數                 78 47043
所有彩種                                 所有天數                252 47055
所有彩種                                 所有天數                278 47057
所有彩種                                 所有天數               8554 47059
所有彩種                                 所有天數                  4 47066

 

40 rows selected

Executed in 0.234 seconds

SQL>

 

總結:通過以上對grouping,cube,rollup的例子介紹,我們就可以很好的做數據統計,最重要的是,語法簡單效率極高

rollup(a,b,c)

彙總方式是按如下規律的
1.a (可以簡單理解爲,每個a總計情況)
2.a,b (可以簡單理解爲,每個(a,b)總計情況)
3.a,b,c  (可以簡單理解爲,每個(a,b,c)總計情況)

 

如果是rollup(a,b,c,d)會是什麼樣呢? 

cube(a,b,c)

1. a
2. a,b
3. a,b,c
4. b
5. b,c
6. c
7. a,c

cube和rollup不同的是,cube(a,b,c...)是彙總統計包含第一個元素a的所有子集,而rollup(a,b,c,...)是彙總統計所有子集的

使用環境:適用於分組統計,可以按着我們自己的要求進行各種複雜的統計

二.rank函數的介紹

rank()樣例:
SQL>   select o.lottery_id,trunc(o.buy_time,'dd'),sum(o.money)
  2     ,rank() over( order by sum(o.money) desc) rank
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time> sysdate -120
  6    
  7    group by o.lottery_id,trunc(o.buy_time,'dd')
  8  ;

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   10 2010-10-13                 19369444          1
                   49 2010-10-13                  2089524          2
                   10 2010-10-22                   750410          3
                   10 2010-10-21                   370164          4
                   53 2010-10-13                   131072          5
                   10 2010-10-20                    73730          6
                   51 2010-10-13                    62208          7
                   14 2010-11-10                     8544          8
                   58 2010-8-23                      6084          9
                   74 2010-9-16                      3238         10
                   58 2010-8-24                      3201         11
                   67 2010-8-11                      2252         12
                   44 2010-8-25                      1458         13
                   58 2010-11-4                      1384         14
                   44 2010-8-19                       736         15
                   22 2010-11-9                       278         16
                   14 2010-11-9                       156         17
                   58 2010-8-26                       132         18
                   74 2010-9-17                       130         19
                   44 2010-8-16                       112         20

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   47 2010-8-24                       106         21
                   58 2010-8-20                       102         22
                   67 2010-8-25                       102         22
                   14 2010-11-8                        96         24
                   58 2010-11-8                        78         25
                   58 2010-8-17                        40         26
                   74 2010-9-15                        32         27
                   44 2010-8-24                        30         28
                   67 2010-9-25                        26         29
                   44 2010-8-17                        20         30
                   14 2010-11-11                       10         31
                   44 2010-8-18                        10         31

                   74 2010-10-12                        8         33
                   67 2010-8-10                         6         34
                   14 2010-11-15                        4         35
                   44 2010-8-23                         4         35
                   58 2010-8-25                         2         37
                   58 2010-8-27                         2         37

38 rows selected

Executed in 0.156 seconds

SQL>

dense_rank()樣例:
SQL>   select o.lottery_id,trunc(o.buy_time,'dd'),sum(o.money)
  2     ,dense_rank() over( order by sum(o.money) desc) rank
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time> sysdate -120
  6    --and o.buy_time< sysdate -30
  7    group by o.lottery_id,trunc(o.buy_time,'dd')
  8  ;

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   10 2010-10-13                 19369444          1
                   49 2010-10-13                  2089524          2
                   10 2010-10-22                   750410          3
                   10 2010-10-21                   370164          4
                   53 2010-10-13                   131072          5
                   10 2010-10-20                    73730          6
                   51 2010-10-13                    62208          7
                   14 2010-11-10                     8544          8
                   58 2010-8-23                      6084          9
                   74 2010-9-16                      3238         10
                   58 2010-8-24                      3201         11
                   67 2010-8-11                      2252         12
                   44 2010-8-25                      1458         13
                   58 2010-11-4                      1384         14
                   44 2010-8-19                       736         15
                   22 2010-11-9                       278         16
                   14 2010-11-9                       156         17
                   58 2010-8-26                       132         18
                   74 2010-9-17                       130         19
                   44 2010-8-16                       112         20

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   47 2010-8-24                       106         21
                   58 2010-8-20                       102         22
                   67 2010-8-25                       102         22
                   14 2010-11-8                        96         23

                   58 2010-11-8                        78         24
                   58 2010-8-17                        40         25
                   74 2010-9-15                        32         26
                   44 2010-8-24                        30         27
                   67 2010-9-25                        26         28
                   44 2010-8-17                        20         29
                   14 2010-11-11                       10         30
                   44 2010-8-18                        10         30
                   74 2010-10-12                        8         31
                   67 2010-8-10                         6         32
                   14 2010-11-15                        4         33
                   44 2010-8-23                         4         33
                   58 2010-8-25                         2         34
                   58 2010-8-27                         2         34

38 rows selected

Executed in 0.125 seconds

 

SQL>

 

 

row_number()樣例:
SQL>   select o.lottery_id,trunc(o.buy_time,'dd'),sum(o.money)
  2     ,row_number() over( order by sum(o.money) desc) rank
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time> sysdate -120
  6    --and o.buy_time< sysdate -30
  7    group by o.lottery_id,trunc(o.buy_time,'dd')
  8  ;

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   10 2010-10-13                 19369444          1
                   49 2010-10-13                  2089524          2
                   10 2010-10-22                   750410          3
                   10 2010-10-21                   370164          4
                   53 2010-10-13                   131072          5
                   10 2010-10-20                    73730          6
                   51 2010-10-13                    62208          7
                   14 2010-11-10                     8544          8
                   58 2010-8-23                      6084          9
                   74 2010-9-16                      3238         10
                   58 2010-8-24                      3201         11
                   67 2010-8-11                      2252         12
                   44 2010-8-25                      1458         13
                   58 2010-11-4                      1384         14
                   44 2010-8-19                       736         15
                   22 2010-11-9                       278         16
                   14 2010-11-9                       156         17
                   58 2010-8-26                       132         18
                   74 2010-9-17                       130         19
                   44 2010-8-16                       112         20

           LOTTERY_ID TRUNC(O.BUY_TIME,'DD') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   47 2010-8-24                       106         21
                   58 2010-8-20                       102         22
                   67 2010-8-25                       102         23
                   14 2010-11-8                        96         24
                   58 2010-11-8                        78         25
                   58 2010-8-17                        40         26
                   74 2010-9-15                        32         27
                   44 2010-8-24                        30         28
                   67 2010-9-25                        26         29
                   44 2010-8-17                        20         30
                   14 2010-11-11                       10         31
                   44 2010-8-18                        10         32
                   74 2010-10-12                        8         33
                   67 2010-8-10                         6         34
                   14 2010-11-15                        4         35
                   44 2010-8-23                         4         36
                   58 2010-8-25                         2         37
                   58 2010-8-27                         2         38

38 rows selected

Executed in 0.172 seconds

SQL>

三個樣例對比結果:

rank:如果出現兩個相同的數據,那麼後面的數據就會直接跳過這個排序號碼
dense_rank:如果出現兩個相同的數據,後面的數據不會跳過這個排序號碼,仍然按順序號碼繼續
row_number:哪怕是兩個數據完全相同,排序號也會不一樣,這個特性在我們想找出對應每個條件的唯一記錄的時候有很大用處

取每個月每個彩種銷售的前三名
SQL> select * from (
  2    select o.lottery_id,trunc(o.buy_time,'mm'),sum(o.money)
  3    ,rank() over(partition by trunc(o.buy_time,'mm') order by sum(o.money) desc) rank
  4     from tb_order o
  5    where o.state=4
  6    and o.buy_time> sysdate -120
  7    --and o.buy_time< sysdate -30
  8    group by o.lottery_id,trunc(o.buy_time,'mm')
  9    )
 10    where rank<4
 11  ;

           LOTTERY_ID TRUNC(O.BUY_TIME,'MM') SUM(O.MONEY)       RANK
--------------------- ---------------------- ------------ ----------
                   58 2010-8-1                       9563          1
                   44 2010-8-1                       2370          2
                   67 2010-8-1                       2360          3
                   74 2010-9-1                       3400          1
                   67 2010-9-1                         26          2
                   10 2010-10-1                  20563748          1
                   49 2010-10-1                   2089524          2
                   53 2010-10-1                    131072          3
                   14 2010-11-1                      8810          1
                   58 2010-11-1                      1462          2
                   22 2010-11-1                       278          3

11 rows selected

Executed in 0.063 seconds

 


取最近銷售的10個訂單信息
SQL> select * from (
  2    select o.id,o.lottery_id,o.buy_time,rank() over(order by o.buy_time desc ) rank
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time > sysdate -30
  6    ) where rank <11
  7  ;

                   ID            LOTTERY_ID BUY_TIME          RANK
--------------------- --------------------- ----------- ----------
           2224442592                    14 2010-11-15           1
           2224442577                    14 2010-11-11           2
           2224442552                    14 2010-11-10           3
           2224442539                    14 2010-11-10           4
           2224442526                    14 2010-11-10           5
           2224442513                    14 2010-11-10           6
           2224442510                    14 2010-11-10           7
           2224442507                    14 2010-11-10           8
           2224442504                    14 2010-11-10           9
           2224442501                    14 2010-11-10          10

10 rows selected

Executed in 0.046 seconds

當然也可以用rownum實現
SQL> 
SQL> select * from (
  2  select o.id,o.lottery_id,o.buy_time,rownum rn
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time > sysdate -30
  6    order by o.buy_time desc
  7  )
  8  where rn<11
  9  ;

                   ID            LOTTERY_ID BUY_TIME            RN
--------------------- --------------------- ----------- ----------
           2224442592                    14 2010-11-15           1
           2224442577                    14 2010-11-11           2
           2224442552                    14 2010-11-10           3
           2224442539                    14 2010-11-10           4
           2224442526                    14 2010-11-10           5
           2224442513                    14 2010-11-10           6
           2224442510                    14 2010-11-10           7
           2224442507                    14 2010-11-10           8
           2224442504                    14 2010-11-10           9
           2224442501                    14 2010-11-10          10

10 rows selected

Executed in 0.031 seconds

SQL>


從這兩個sql的執行計劃看,他們選擇了不同索引,rownum選擇的索引更高效一點


使用環境:rank分析函數主要用於分組統計排名或排序,取分組內前N行數據等場景

 

 


三. lag和lead函數介紹

取每個月的上個月和下個月的銷售額度
SQL> select lottery_id,buy_time,money,
  2  lag(money,2,0) over( partition by lottery_id  order by buy_time) pre_month_money,
  3  lag(money,1,0) over( partition by lottery_id  order by buy_time) last_month_money,
  4  lead(money,1,0) over( partition by lottery_id  order by buy_time) next_month_money,
  5  lead(money,2,0) over( partition by lottery_id  order by buy_time) post_month_money
  6  from
  7  (
  8  select o.lottery_id,trunc(o.buy_time,'dd') buy_time ,sum(o.money) money
  9     from tb_order o
 10    where o.state=4
 11    and o.buy_time > sysdate -150
 12    group by o.lottery_id,trunc(o.buy_time,'dd')
 13    )
 14  ;

           LOTTERY_ID BUY_TIME         MONEY PRE_MONTH_MONEY LAST_MONTH_MONEY NEXT_MONTH_MONEY POST_MONTH_MONEY
--------------------- ----------- ---------- --------------- ---------------- ---------------- ----------------
                   10 2010-10-13    19369444               0                0            73730           370164
                   10 2010-10-20       73730               0         19369444           370164           750410
                   10 2010-10-21      370164        19369444            73730           750410                0
                   10 2010-10-22      750410           73730           370164                0                0
                   14 2010-7-28           34               0                0              366               96
                   14 2010-7-29          366               0               34               96              156
                   14 2010-11-8           96              34              366              156             8544
                   14 2010-11-9          156             366               96             8544               10
                   14 2010-11-10        8544              96              156               10                4
                   14 2010-11-11          10             156             8544                4                0
                   14 2010-11-15           4            8544               10                0                0
                   22 2010-11-9          278               0                0                0                0
。。。

53 rows selected

Executed in 0.204 seconds

SQL>

 


說明:利用lag和lead函數,我們可以在同一行中顯示前n行的數據,也可以顯示後n行的數據.

 

LAG ( value_expr [, offset] [, default] ) OVER ( [query_partition_clause] order_by_clause )
LEAD ( value_expr [, offset] [, default] )  OVER ( [query_partition_clause] order_by_clause )

 

如果不指定offset(偏移量),默認值爲1。如果offset(偏移量)超出窗口範圍,則返回可指定默認值。如不指定默認值,則默認值爲null。


使用環境:lag和lead函數主要用於把當前行和前後N行數據放在同一行裏顯示的場景 

四. sum,avg,max,min移動計算數據介紹

取最近一個內,連續3天的銷售總額,平均額,最大額,最小額
SQL> select lottery_id,buy_time,money,
  2  sum(money) over (partition by lottery_id order by buy_time range between 1 preceding and 1 following) "3days_sum",
  3  avg(money) over (partition by lottery_id order by buy_time range between 1 preceding and 1 following) "3days_avg",
  4  max(money) over (partition by lottery_id order by buy_time range between 1 preceding and 1 following) "3days_max",
  5  min(money) over (partition by lottery_id order by buy_time range between 1 preceding and 1 following) "3days_min"
  6  from
  7  (
  8  select o.lottery_id,trunc(o.buy_time,'dd') buy_time ,sum(o.money) money
  9     from tb_order o
 10    where o.state=4
 11    and o.buy_time > sysdate -30
 12    group by o.lottery_id,trunc(o.buy_time,'dd')
 13    )
 14  ;

           LOTTERY_ID BUY_TIME         MONEY  3days_sum  3days_avg  3days_max  3days_min
--------------------- ----------- ---------- ---------- ---------- ---------- ----------
                   14 2010-11-8           96        252        126        156         96
                   14 2010-11-9          156       8796       2932       8544         96
                   14 2010-11-10        8544       8710 2903.33333       8544         10
                   14 2010-11-11          10       8554       4277       8544         10
                   14 2010-11-15           4          4          4          4          4
                   22 2010-11-9          278        278        278        278        278
                   58 2010-11-8           78         78         78         78         78

7 rows selected

Executed in 0.031 seconds

說明:

開窗函數指定了分析函數工作的數據窗口大小,這個數據窗口大小可能會隨着行的變化而變化,舉例如下:
over(order by salary) 按照salary排序進行累計,order by是個默認的開窗函數
over(partition by deptno)按照部門分區
over(order by salary range between 50 preceding and 150 following)每行對應的數據窗口是之前行幅度值不超過50,之後行幅度值不超過150
over(order by salary rows between 50 preceding and 150 following)每行對應的數據窗口是之前50行,之後150行
over(order by salary rows between unbounded preceding and unbounded following)每行對應的數據窗口是從第一行到最後一行
over(order by salary range between unbounded preceding and unbounded following) 每行對應的數據窗口是從最大值到最小值

五. ratio_to_report函數的介紹

取每天每個彩種銷售佔比的情況
SQL>   select o.lottery_id,trunc(o.buy_time,'dd') buy_time ,sum(o.money) money,
  2    ratio_to_report(sum(o.money)) over (partition by trunc(o.buy_time,'dd') )
  3     from tb_order o
  4    where o.state=4
  5    and o.buy_time > sysdate -30
  6    group by trunc(o.buy_time,'dd'),o.lottery_id
  7  ;

           LOTTERY_ID BUY_TIME         MONEY RATIO_TO_REPORT(SUM(O.MONEY))O
--------------------- ----------- ---------- ------------------------------
                   14 2010-11-8           96              0.551724137931034
                   58 2010-11-8           78              0.448275862068966
                   14 2010-11-9          156              0.359447004608295
                   22 2010-11-9          278              0.640552995391705
                   14 2010-11-10        8544                              1
                   14 2010-11-11          10                              1
                   14 2010-11-15           4                              1

7 rows selected

Executed in 0.031 seconds

SQL>


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