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

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

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

    紙飛機

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

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

    解決方案

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

    DB2和Oracle

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

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

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

    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

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

    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.     計算各自的自然對數(shù)

    2.     計算這些對數(shù)的和

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

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

    DB2和Oracle

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

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

    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

    觀察一下,會發(fā)現(xiàn)SAL[1]的值為-1300。由于數(shù)字逐一連續(xù)遞增、沒有間隙,所以可以通過減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行的當前值(函數(shù)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節(jié)。

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

    posted on 2008-05-14 21:40 紙飛機 閱讀(1418) 評論(0)  編輯  收藏 所屬分類: Database
    主站蜘蛛池模板: 久久久久久久岛国免费播放 | 成人最新午夜免费视频| 亚洲AV成人片色在线观看高潮| 成人免费网站视频www| 免费国产在线观看| 老湿机一区午夜精品免费福利| 国产小视频免费观看| 极品色天使在线婷婷天堂亚洲| 免费va人成视频网站全| 视频免费1区二区三区| 国产乱辈通伦影片在线播放亚洲| 一级毛片完整版免费播放一区| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 一区二区三区亚洲视频| 综合偷自拍亚洲乱中文字幕| 国产一级淫片免费播放电影| 国产精品福利片免费看| 亚洲av激情无码专区在线播放| 99久久99久久精品免费看蜜桃 | 亚洲成a人片在线观| 久久久久久99av无码免费网站 | 亚洲精品无码久久久久A片苍井空| 日韩一级在线播放免费观看| 成年免费大片黄在线观看com| 国产亚洲成av片在线观看| 91精品国产免费久久国语麻豆| 国产亚洲国产bv网站在线| 性做久久久久免费看| 一区二区三区免费视频观看| 亚洲国产一区二区三区青草影视| 曰批全过程免费视频播放网站 | 亚洲国产成人久久综合碰| 最近中文字幕大全免费版在线| 亚洲国产成人精品无码区在线秒播| 女性自慰aⅴ片高清免费| 一级特级aaaa毛片免费观看 | 亚洲国产一成久久精品国产成人综合 | 91在线品视觉盛宴免费| 一级黄色免费大片| 亚洲免费中文字幕| 亚洲国产成人影院播放|