<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    紙飛機

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      22 隨筆 :: 28 文章 :: 30 評論 :: 0 Trackbacks

    問題:計算某個數字列的累乘積。其操作方式與“計算累計和”相似,只是使用乘法而不是加法。

    解決方案

    作為例子,本解決方案中都計算職員工資的累乘積。雖然工資的累乘積沒有多大用處,然而可以很容易地把該技巧用于其他更有用的領域。

    DB2和Oracle

    使用窗口函數SUM OVER,用對數相加來模擬乘法操作:

    1 select empno,ename,sal,

    2         exp(sum(ln(sal))over(order by sal,empno)) as running_prod

    3    from emp

    4   where deptno = 10

    EMPNO ENAME        SAL          RUNNING_PROD

    ----- ---------- ---- --------------------

    7934 MILLER      1300                  1300

    7782 CLARK       2450               3185000

    7839 KING        5000           15925000000

    在SQL中,對小于等于0的值取對數是無效的。如果表中包含這樣的值,一定要避免把這些無效的值傳遞給SQL的LN函數。為了增加可讀性,該解決方案并沒有對無效值和NULL值采取防范措施,但自己編寫代碼時,一定要考慮是否需要這種預防。如果一定要用到負值和0值,那么這種解決方案不合適。

    Oracle獨有的另一種解決方案是使用Oracle Database 10g新引入的MODEL子句。在下面的例子中,每個SAL都是負數,這表明累乘積允許出現負值:

    1 select empno, ename, sal, tmp as running_prod

    2    from (

    3 select empno,ename,-sal as sal

    4    from emp

    5   where deptno=10

    6         )

    7   model

    8     dimension by(row_number()over(order by sal desc) rn )

    9     measures(sal, 0 tmp, empno, ename)

    10    rules (

    11      tmp[any] = case when sal[cv()-1] is null then sal[cv()]

    12                      else tmp[cv()-1]*sal[cv()]

    13                 end

    14    )

    EMPNO ENAME        SAL          RUNNING_PROD

    ----- ---------- ---- --------------------

    7934 MILLER      -1300                -1300

    7782 CLARK       -2450              3185000

    7839 KING        -5000         -15925000000

    MySQL、PostgreSQL和SQL Server

    還可以使用對數相加的方法,但這些平臺并不支持窗口函數,因此用標量子查詢取而代之:

    1 select e.empno,e.ename,e.sal,

    2         (select exp(sum(ln(d.sal)))

    3            from emp d

    4           where d.empno <= e.empno

    5             and e.deptno=d.deptno) as running_prod

    6   from emp e

    7   where e.deptno=10

    EMPNO ENAME        SAL          RUNNING_PROD

    ----- ---------- ---- --------------------

    7782 CLARK       2450                  2450

    7839 KING        5000              12250000

    7934 MILLER      1300           15925000000

    SQL Server用戶使用LOG代替LN。

    討論

    除了MODEL子句方案(僅對Oracle Database 10g或更高版本可用)之外,所有解決方案都利用了乘法運算的特性,按下列步驟用加法進行計算:

    1.     計算各自的自然對數

    2.     計算這些對數的和

    3.     對結果進行數學常量e的冪運算(使用EXP函數)

    當采用這種方法時,需要注意,對于0值和負值,這種方法不可行,因為任何小于等于0的值都超出了SQL對數的定義域。

    DB2和Oracle

    有關窗口函數SUM OVER的功能,請參閱“生成累計和”一節。

    對于Oracle Database 10g或更高版本,可以使用MODEL子句生成累乘積。同時使用MODEL子句及窗口函數ROW_NUMBER,很容易就能訪問前面的行。可以像訪問數組一樣訪問MEASURES列表中的每一項。然后,可以使用DIMENSIONS列表中的項(由ROW_NUMBER返回的值,別名RN)搜索該數組:

    select empno, ename, sal, tmp as running_prod,rn

       from (

    select empno,ename,-sal as sal

       from emp

    where deptno=10

            )

    model

        dimension by(row_number()over(order by sal desc) rn )

        measures(sal, 0 tmp, empno, ename)

       rules ()

    EMPNO ENAME              SAL RUNNING_PROD          RN

    ----- ---------- ---------- ------------ ----------

    7934 MILLER           -1300             0           1

    7782 CLARK            -2450             0           2

    7839 KING             -5000             0           3

    觀察一下,會發現SAL[1]的值為-1300。由于數字逐一連續遞增、沒有間隙,所以可以通過減1來引用前一行。RULES子句如下:

    rules (

        tmp[any] = case when   sal[cv()-1] is null then sal[cv()]

                        else tmp[cv()-1]*sal[cv()]

                   end

    )

    它使用內置操作符ANY處理每一行,而并未進行硬編碼。這個例子中ANY的值分別為1、2和3。把TMP[n]初始化為0。通過計算相應SAL行的當前值(函數CV返回當前值),可以給TMP[n]指定一個值。把TMP[1]初始化為0,把SAL[1]初始化為-1300。SAL[0]沒有值,所以把TMP[1]設置為SAL[1]。在設置了TMP[1]之后,下一行就是TMP[2]。計算第一個SAL[1](由于ANY的當前值是2,因此SAL[CV()-1]的值是SAL[1])。SAL[1]不為空,而且等于-1300,因此把TMP[2]設置為TMP[1]和SAL[2]的乘積。所有行都進行上述操作。

    MySQL、PostgreSQL和SQL Server

    有關MySQL、PostgreSQL和SQL Server解決方案所采用的子查詢方法的說明,請參閱本章第7.6節。

    要注意,基于子查詢解決方案的輸出與Oracle和DB2解決方案的輸出有少許差別,其原因來自EMPNO比較(它們按不同的順序計算累乘積)。與累計和一樣,其總數也是由標量子查詢的謂詞驅動的;在該解決方案中,行是按EMPNO排序的,而對于Oracle/DB2 解決方案,行是按SAL排序的。

    posted on 2008-05-14 21:40 紙飛機 閱讀(1418) 評論(0)  編輯  收藏 所屬分類: Database
    主站蜘蛛池模板: 亚洲人成电影亚洲人成9999网| 国产jizzjizz免费视频| 国产成人A人亚洲精品无码| 亚洲精品黄色视频在线观看免费资源 | 亚洲一区动漫卡通在线播放| 在线观看永久免费| jlzzjlzz亚洲jzjzjz| 人妻视频一区二区三区免费| 亚洲色大成网站www尤物| 国产美女无遮挡免费网站| 国产亚洲精品第一综合| 久久夜色精品国产亚洲av| 中文无码成人免费视频在线观看| 午夜亚洲www湿好大| 4虎永免费最新永久免费地址| 亚洲小说图区综合在线| mm1313亚洲精品无码又大又粗| 国产99久久久国产精免费| 亚洲日韩区在线电影| 国产成人无码免费看视频软件| 亚洲国产精品成人午夜在线观看| 久久精品亚洲乱码伦伦中文| 最近2019年免费中文字幕高清| 亚洲精品免费网站| 亚洲综合另类小说色区色噜噜| 日本高清免费观看| 亚洲人成网站免费播放| 亚洲综合色区在线观看| 免费成人福利视频| 中文字幕久无码免费久久| 亚洲四虎永久在线播放| 拍拍拍又黄又爽无挡视频免费| 色www免费视频| 免费观看美女裸体网站| 一区二区三区在线免费 | 日本v片免费一区二区三区| 精品一区二区三区免费观看| 亚洲婷婷天堂在线综合| 亚洲熟妇少妇任你躁在线观看无码| 3d成人免费动漫在线观看| 免费一级全黄少妇性色生活片|