Oracle中實現連乘(二)
Oracle有連加的聚集函式SUM,但是沒有一個連乘的函式。
Oracle中實現連乘(一):http://yangtingkun.itpub.net/post/468/466369
在上一篇文章的最後給出了利用指數和對數的方法,配合簡單的SUM就得到了連乘的結果。上文也提到了,這種方法唯一的缺點是,在處理大資料量計算的時候,可能由於LOG和POWER運算,而引入一些小的誤差。
網友raiseup.net提出置疑,認為“直接用SQL函式組合的話,精度損失不是唯一的缺點,比較要命的是無法處理0和負數的資料。”
首先從數學的角度講,這種看法是正確的,不過這個問題其實很容易就可以透過變通的方法來解決。
先說0的問題,只要連乘的數中包含了0,那麼最終的結果一定是0,基於這一點考慮,修改SQL如下:
SQL> WITH T AS (SELECT ROWNUM RN FROM TAB)
2 SELECT POWER(10, SUM(LOG(10, RN))) MULTI
3 FROM T;
MULTI
----------
362880
SQL> WITH T AS (SELECT ROWNUM - 1 RN FROM TAB)
2 SELECT POWER(10, SUM(LOG(10, RN))) MULTI
3 FROM T;
SELECT POWER(10, SUM(LOG(10, RN))) MULTI
*
第 2 行出現錯誤:
ORA-01428: 引數 '0' 超出範圍
SQL> WITH T AS (SELECT ROWNUM RN FROM TAB)
2 SELECT DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
3 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, RN)))) MULTI
4 FROM T;
MULTI
----------
362880
SQL> WITH T AS (SELECT ROWNUM - 1 RN FROM TAB)
2 SELECT DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
3 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, RN)))) MULTI
4 FROM T;
MULTI
----------
0
只需要對0進行簡單的處理,就可以解決問題。查詢的被乘數的含義是:對0的個數進行SUM,如果SUM的結果是0,說明連乘的數中不包含0,則被乘數為1,不改變乘數的結果。如果SUM的結果不為0,說明連乘的數中包含了一個以上的0,那麼這時將被乘數設定為0,不管後面計算的結果是什麼,最終的結果都返回0,需要注意,由於0不能進行LOG操作,因此在後面處理的時候需要進行轉變。
對於負數的處理其實也很簡單,只需要記錄將負數按照正數來處理,並記錄出現負數的次數就可以了:
SQL> WITH T AS (SELECT ROWNUM - 2 RN FROM TAB)
2 SELECT DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
3 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, RN)))) MULTI
4 FROM T;
* POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, RN)))) MULTI
*
第 3 行出現錯誤:
ORA-01428: 引數 '-1' 超出範圍
SQL> WITH T AS (SELECT ROWNUM - 2 RN FROM TAB)
2 SELECT POWER(-1, MOD(SUM(DECODE(SIGN(RN), -1, 1, 0)), 2))
3 * DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
4 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, ABS(RN))))) MULTI
5 FROM T
6 ;
MULTI
----------
0
SQL> WITH T AS (SELECT ROWNUM - 2 RN FROM TAB)
2 SELECT POWER(-1, MOD(SUM(DECODE(SIGN(RN), -1, 1, 0)), 2))
3 * DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
4 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, ABS(RN))))) MULTI
5 FROM T
6 WHERE RN != 0;
MULTI
----------
-5040
SQL> WITH T AS (SELECT ROWNUM - 3 RN FROM TAB)
2 SELECT POWER(-1, MOD(SUM(DECODE(SIGN(RN), -1, 1, 0)), 2))
3 * DECODE(SUM(DECODE(RN, 0, 1, 0)), 0, 1, 0)
4 * POWER(10, SUM(LOG(10, DECODE(RN, 0, 1, ABS(RN))))) MULTI
5 FROM T
6 WHERE RN != 0;
MULTI
----------
1440
第一個被乘數就是計算連乘的數字中,負數出現的個數,並根據這個個數判斷最終結果的正負,而在計算連乘的時候,則只計算數值絕對值的連乘,不考慮正負數。
其實就是對上一篇文章中SQL的一個簡單的變形,這篇文章單獨寫出來,目的其實是想說明最基礎的東西有了,如何利用基礎的東西來實現自己的功能。
SQL實現如此,DBA不少的工作也是如此,Oracle提供了大量的基礎的功能,DBA如何根據Oracle提供的功能來進行定製、修改,最終實現自己想要的功能,這不僅需要DBA對於Oracle提供的基礎功能有詳細的瞭解,還需要DBA自己大膽設想,做到Tom提到的think out of the box。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-604867/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle中實現連乘Oracle
- Oracle實現連乘的辦法Oracle
- Oracle中實現圓周率計算(二)Oracle
- Oracle SQL實現階乘的幾個方法OracleSQL
- python中連乘怎麼算?Python
- 矩陣連乘矩陣
- 數值分析:最小二乘與嶺迴歸(Pytorch實現)PyTorch
- c語言實現階乘C語言
- 用單連結串列實現多項式加,減,乘,簡單微分
- c#遞迴實現 階乘C#遞迴
- 點乘和叉乘及其物理意義(C++STL實現)點乘C++
- 矩陣連乘問題矩陣
- hdu 1757 矩陣連乘矩陣
- 快速冪演算法(二分思想減少連乘次數)演算法
- java不用api實現單連結串列反轉(二)JavaAPI
- 最小二乘(LS)與總體最小二乘(TLS)總結一TLS
- Oracle Memory Management and HugePage (連載二)Oracle
- 理解最小二乘解
- 在Oracle中實現定時操作Oracle
- oracle中的連線Oracle
- 利用Oracle VPD實現行級安全保護(二)Oracle
- oracle中通過decode實現行變列的二維表統計展示Oracle
- PowerDesigner實現Oracle資料庫連線生成模型Oracle資料庫模型
- 連載二:Oracle遷移文章大全Oracle
- django中的資料庫連線池實現Django資料庫
- ORACLE中實現表變數的方法Oracle變數
- Oracle中實現圓周率計算(三)Oracle
- Oracle中實現圓周率計算(一)Oracle
- 梯度下降求解最小二乘梯度
- 最小二乘與梯度下降梯度
- 動態規劃&矩陣連乘動態規劃矩陣
- 【數學】向量點乘、叉乘的理論、應用及程式碼實現(C++)點乘C++
- vlsm實現(二)
- MyBatis入門學習-連線oracle實現CURD基本操作MyBatisOracle
- Java用OCI驅連Oracle資料庫的實現方法JavaOracle資料庫
- MYSQL INNODB 中通用雙向連結串列的實現MySql
- c#(WPF)實現連連看C#
- Oracle中表的連線及其調整(二)Oracle