亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Oracle > 正文

Oracle開發之窗口函數

2024-08-29 13:59:06
字體:
來源:轉載
供稿:網友

一、窗口函數簡介:

到目前為止,我們所學習的分析函數在計算/統計一段時間內的數據時特別有用,但是假如計算/統計需要隨著遍歷記錄集的每一條記錄而進行呢?舉些例子來說:

①列出每月的訂單總額以及全年的訂單總額
②列出每月的訂單總額以及截至到當前月的訂單總額
③列出上個月、當月、下一月的訂單總額以及全年的訂單總額
④列出每天的營業額及一周來的總營業額
⑤列出每天的營業額及一周來每天的平均營業額

仔細回顧一下前面我們介紹到的分析函數,我們會發現這些需求和前面有一些不同:前面我們介紹的分析函數用于計算/統計一個明確的階段/記錄集,而這里有部分需求例如2,需要隨著遍歷記錄集的每一條記錄的同時進行統計。

也即是說:統計不止發生一次,而是發生多次。統計不至發生在記錄集形成后,而是發生在記錄集形成的過程中。

這就是我們這次要介紹的窗口函數的應用了。它適用于以下幾個場合:

①通過指定一批記錄:例如從當前記錄開始直至某個部分的最后一條記錄結束
②通過指定一個時間間隔:例如在交易日之前的前30天
③通過指定一個范圍值:例如所有占到當前交易量總額5%的記錄

二、窗口函數示例-全統計:

下面我們以需求:列出每月的訂單總額以及全年的訂單總額為例,來看看窗口函數的應用。

【1】測試環境:

 

復制代碼 代碼如下:
SQL> desc orders;

 

 名稱                    是否為空? 類型
 ----------------------- -------- ----------------
 MONTH                            NUMBER(2)
 TOT_SALES                    NUMBER

SQL>

【2】測試數據:

 

復制代碼 代碼如下:
SQL> select * from orders;

 

     MONTH  TOT_SALES
---------- ----------
         1     610697
         2     428676
         3     637031
         4     541146
         5     592935
         6     501485
         7     606914
         8     460520
         9     392898
        10     510117
        11     532889
        12     492458

已選擇12行。

【3】測試語句:

回憶一下前面《Oracle開發專題之:分析函數(OVER)》一文中,我們使用了sum(sum(tot_sales)) over (partition by region_id) 來統計每個分區的訂單總額?,F在我們要統計的不單是每個分區,而是所有分區,partition by region_id在這里不起作用了。

Oracle為這種情況提供了一個子句:rows between ... preceding and ... following。從字面上猜測它的意思是:在XXX之前和XXX之后的所有記錄,實際情況如何讓我們通過示例來驗證:

 

復制代碼 代碼如下:
SQL> select month,
         sum(tot_sales) month_sales,
         sum(sum(tot_sales)) over (order by month
            rows between unbounded preceding and unbounded following) total_sales
    from orders
   group by month;

 

     MONTH MONTH_SALES TOTAL_SALES
---------- ----------- -----------
         1      610697     6307766
         2      428676     6307766
         3      637031     6307766
         4      541146     6307766
         5      592935     6307766
         6      501485     6307766
         7      606914     6307766
         8      460520     6307766
         9      392898     6307766
        10      510117     6307766
        11      532889     6307766
        12      492458     6307766

已選擇12行。

綠色高亮處的代碼在這里發揮了關鍵作用,它告訴oracle統計從第一條記錄開始至最后一條記錄的每月銷售額。這個統計在記錄集形成的過程中執行了12次,這時相當費時的!但至少我們解決了問題。

unbounded preceding and unbouned following的意思針對當前所有記錄的前一條、后一條記錄,也就是表中的所有記錄。那么假如我們直接指定從第一條記錄開始直至末尾呢?看看下面的結果:

 

復制代碼 代碼如下:
SQL> select month,
         sum(tot_sales) month_sales,
         sum(sum(tot_sales)) over (order by month
            rows between 1 preceding and unbounded following) all_sales
    from orders
   group by month;

 

     MONTH MONTH_SALES  ALL_SALES
---------- ----------- ----------
         1      610697    6307766
         2      428676    6307766
         3      637031    5697069
         4      541146    5268393
         5      592935    4631362
         6      501485    4090216
         7      606914    3497281
         8      460520    2995796
         9      392898    2388882
        10      510117    1928362
        11      532889    1535464
        12      492458    1025347

已選擇12行。

很明顯這個語句錯了。實際1在這里不是從第1條記錄開始的意思,而是指當前記錄的前一條記錄。preceding前面的修飾符是告訴窗口函數執行時參考的記錄數,如同unbounded就是告訴oracle不管當前記錄是第幾條,只要前面有多少條記錄,都列入統計的范圍。

三、窗口函數進階-滾動統計(累積/均值):

考慮前面提到的第2個需求:列出每月的訂單總額以及截至到當前月的訂單總額。也就是說2月份的記錄要顯示當月的訂單總額和1,2月份訂單總額的和。3月份要顯示當月的訂單總額和1,2,3月份訂單總額的和,依此類推。

很明顯這個需求需要在統計第N月的訂單總額時,還要再統計這N個月來的訂單總額之和。想想上面的語句,假如我們能夠把and unbounded following換成代表當前月份的邏輯多好??!很幸運的是Oracle考慮到了我們這個需求,為此我們只需要將語句稍微改成: curreent row就可以了。

 

復制代碼 代碼如下:
SQL> select month,
         sum(tot_sales) month_sales,
         sum(sum(tot_sales)) over(order by month
           rows between unbounded preceding and current row) current_total_sales
    from orders
   group by month;

 

     MONTH MONTH_SALES CURRENT_TOTAL_SALES
---------- ----------- -------------------
         1      610697              610697
         2      428676             1039373
         3      637031             1676404
         4      541146             2217550
         5      592935             2810485
         6      501485             3311970
         7      606914             3918884
         8      460520             4379404
         9      392898             4772302
        10      510117             5282419
        11      532889             5815308
        12      492458             6307766

已選擇12行。

現在我們能得到滾動的銷售總額了!下面這個統計結果看起來更加完美,它展現了所有我們需要的數據:

 

復制代碼 代碼如下:
SQL> select month,
         sum(tot_sales) month_sales,
         sum(sum(tot_sales)) over(order by month
         rows between unbounded preceding and current row) current_total_sales,
         sum(sum(tot_sales)) over(order by month
         rows between unbounded preceding and unbounded following) total_sales
    from orders
   group by month;

 

     MONTH MONTH_SALES CURRENT_TOTAL_SALES TOTAL_SALES
---------- ----------- ------------------- -----------
         1      610697              610697     6307766
         2      428676             1039373     6307766
         3      637031             1676404     6307766
         4      541146             2217550     6307766
         5      592935             2810485     6307766
         6      501485             3311970     6307766
         7      606914             3918884     6307766
         8      460520             4379404     6307766
         9      392898             4772302     6307766
        10      510117             5282419     6307766
        11      532889             5815308     6307766
        12      492458             6307766     6307766

已選擇12行。

在一些銷售報表中我們會時??吹角笃骄档男枨?,有時可能是針對全年的數據求平均值,有時會是針對截至到當前的所有數據求平均值。很簡單,只需要將:
sum(sum(tot_sales))換成avg(sum(tot_sales))即可。

四、窗口函數進階-根據時間范圍統計:

前面我們說過,窗口函數不單適用于指定記錄集進行統計,而且也能適用于指定范圍進行統計的情況,例如下面這個SQL語句就統計了當天銷售額和五天內的評價銷售額:
 

復制代碼 代碼如下:
select trunc(order_dt) day,
    sum(sale_price) daily_sales,
    avg(sum(sale_price)) over (order by trunc(order_dt)
    range between interval '2' day preceding
    and interval '2' day following
) five_day_avg
from cust_order
where sale_price is not null
    and order_dt between to_date('01-jul-2001','dd-mon-yyyy')
    and to_date('31-jul-2001','dd-mon-yyyy')

 

為了對指定范圍進行統計,Oracle使用關鍵字range、interval來指定一個范圍。上面的例子告訴Oracle查找當前日期的前2天,后2天范圍內的記錄,并統計其銷售平均值。

五、窗口函數進階-first_value/last_value:

Oracle提供了2個額外的函數:first_value、last_value,用于在窗口記錄集中查找第一條記錄和最后一條記錄。假設我們的報表需要顯示當前月、上一個月、后一個月的銷售情況,以及每3個月的銷售平均值,這兩個函數就可以派上用場了。

 

復制代碼 代碼如下:
select month,
    first_value(sum(tot_sales)) over (order by month
    rows between 1 preceding and 1 following) prev_month,
    sum(tot_sales) monthly_sales,
    last_value(sum(tot_sales)) over (order by month
    rows between 1 preceding and 1 following) next_month,
    avg(sum(tot_sales)) over (order by month 
    rows between 1 preceding and 1 following) rolling_avg
from orders
where year = 2001
    and region_id = 6
group by month
order by month;

 

首先我們來看:rows between 1 preceding and 1 following告訴Oracle在當前記錄的前一條、后一條范圍內查找并統計,而first_value和last_value在這3條記錄中至分別找出第一條、第三條記錄,這樣我們就輕松地得到相鄰三個月的銷售記錄及平均值了!

六、窗口函數進階-比較相鄰記錄:

通過第五部分的學習,我們知道了如何利用窗口函數來顯示相鄰的記錄,現在假如我們想每次顯示當月的銷售額和上個月的銷售額,應該怎么做呢?

從第五部分的介紹我們可以知道,利用first_value(sum(tot_sales) over (order by month rows between 1 preceding and 0 following))就可以做到了,其實Oracle還有一個更簡單的方式讓我們來比較2條記錄,它就是lag函數。

leg函數類似于preceding和following子句,它能夠通過和當前記錄的相對位置而被應用,在比較同一個相鄰的記錄集內兩條相鄰記錄的時候特別有用。

 

復制代碼 代碼如下:
select  month,
    sum(tot_sales) monthly_sales,
    lag(sum(tot_sales), 1) over (order by month) prev_month_sales
from orders
where year = 2001
    and region_id = 6
group by month
order by month;

 

lag(sum(tot_sales),1)中的1表示以1月為基準。

以上就是Oracle窗口函數用法的全部內容,希望能給大家一個參考,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到oracle教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲肉体裸体xxxx137| 68精品国产免费久久久久久婷婷| 成人有码视频在线播放| 亚洲欧美在线一区二区| 欧美日韩激情视频| 久久成人在线视频| 国产精品揄拍500视频| 91久久久久久久久久| 中文字幕亚洲欧美一区二区三区| 国产午夜精品免费一区二区三区| 97视频在线免费观看| 日韩美女在线看| 日韩精品在线观看视频| 91精品免费看| 国产精品久久视频| 国产精品久久久久久久久久久久| 国产+人+亚洲| 国产亚洲欧洲高清| 成人黄色大片在线免费观看| 亚洲国产精品人久久电影| 日韩视频亚洲视频| 91国偷自产一区二区三区的观看方式| 国产精品久久久久91| 久久精品国产成人精品| 欧美日本亚洲视频| 97精品久久久中文字幕免费| 日韩一区二区欧美| y97精品国产97久久久久久| 欧美日韩国产色视频| 4p变态网欧美系列| 国产欧美最新羞羞视频在线观看| 黑人与娇小精品av专区| 免费av在线一区| 91亚洲va在线va天堂va国| 国产精品麻豆va在线播放| 这里只有精品视频| 精品毛片三在线观看| 色妞在线综合亚洲欧美| 欧美丝袜第一区| 九九久久精品一区| 久久久久久久网站| 欧美大尺度激情区在线播放| 欧美午夜视频在线观看| 九九久久精品一区| 一区二区三区高清国产| 久久精品国产精品亚洲| 日韩www在线| 日韩欧美在线一区| 亚洲精品电影网站| 日本精品久久久| 91精品久久久久久久久不口人| 精品国产自在精品国产浪潮| 蜜月aⅴ免费一区二区三区| 亚洲丁香久久久| 久国内精品在线| 欧美激情二区三区| 国产精品视频yy9099| 国产91精品黑色丝袜高跟鞋| 成人性生交大片免费看小说| 欧美理论电影在线观看| 一本一本久久a久久精品牛牛影视| 超碰91人人草人人干| 久久亚洲成人精品| 久久777国产线看观看精品| 91沈先生作品| 欧美中文在线视频| 日韩欧美综合在线视频| 中文字幕av一区二区三区谷原希美| 色偷偷噜噜噜亚洲男人| 精品香蕉在线观看视频一| 精品偷拍各种wc美女嘘嘘| 亚洲国产美女精品久久久久∴| 日韩av资源在线播放| 亚洲精品久久久一区二区三区| 国产色视频一区| 国产欧美中文字幕| 国产不卡av在线| 黑人与娇小精品av专区| 亚洲国产成人爱av在线播放| 一二美女精品欧洲| 日韩动漫免费观看电视剧高清| 国产日本欧美在线观看| 亚洲影院色无极综合| 国产精品精品一区二区三区午夜版| 日韩精品免费在线| 国产精品免费一区二区三区都可以| 日韩网站在线观看| 国产精品wwww| 在线日韩欧美视频| 欧美黑人一级爽快片淫片高清| 亚洲男子天堂网| 欧美性在线观看| 国产视频欧美视频| 久久久久国产精品免费网站| 欧美性视频网站| 亚洲国产精品99久久| 91成人在线视频| 欧美激情久久久久久| 26uuu日韩精品一区二区| 久久久免费高清电视剧观看| 日韩欧美一区二区三区久久| 在线精品播放av| 亚洲欧美日韩区| 久久伊人精品天天| 亚洲第一免费网站| 国产成人综合精品| 亚洲图片在区色| 97超级碰碰人国产在线观看| 欧美高清视频在线观看| 97超视频免费观看| 日韩欧美极品在线观看| 亚洲精品国产美女| 日韩av在线不卡| 亚洲精品一区久久久久久| 国内精品久久久久影院 日本资源| 国产成人高潮免费观看精品| 国产亚洲精品美女久久久| 国产999精品| 欧美成人激情视频免费观看| 欧美亚洲一区在线| 国内精品在线一区| 国产精品福利无圣光在线一区| 92看片淫黄大片看国产片| 68精品国产免费久久久久久婷婷| 欧美又大又硬又粗bbbbb| 自拍偷拍亚洲一区| 亚洲有声小说3d| 91精品视频大全| 动漫精品一区二区| 成人免费视频在线观看超级碰| 国产亚洲精品美女久久久久| 国产精品久久久久aaaa九色| 97国产精品视频| 欧美日韩国产二区| 91精品视频免费观看| 亚洲日韩欧美视频一区| 91久久国产婷婷一区二区| 欧美日韩免费观看中文| 91久久精品视频| 亚洲高清久久网| 久久精品91久久久久久再现| 国产精品福利在线观看网址| 欧美亚洲另类制服自拍| 91九色综合久久| 日韩欧美中文字幕在线播放| 国产丝袜精品第一页| 黄色成人在线播放| 精品女厕一区二区三区| 成人黄色网免费| 亚洲免费成人av电影| 国产激情视频一区| 亚洲一区二区三区毛片| 国产精品高潮粉嫩av| 国产一区二区三区精品久久久| 精品成人av一区| 北条麻妃一区二区在线观看| 亚洲图片欧美午夜| 国产精品第一第二| 视频在线观看一区二区| 国产一区欧美二区三区| 国产日韩欧美在线观看| 黑人精品xxx一区一二区| 欧亚精品在线观看| 91九色国产社区在线观看|