Oracle聚合求和和聚合求积(顺便解决BOM展开的问题)
2013-11-17 21:14
531 查看
本文参考网址:http://www.itpub.net/thread-1020772-1-1.html
我们在日常的工作中,经常遇到了针对某一列的值,进行求和,求平均值,在一些特殊的业务场景下,我们需要对某一列进行求积操作,那我们该如何实现呢,下面先介绍,我
们对字符串的求和操作。
针对字符串的求和操作:
1、有分隔符的字符串:
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/a4b3dab88ed69042677aff5db1870dff.jpg)
2、没有分割符符号的:
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/17ddb9dcaeacbaf496aeecd2352f53a8.jpg)
下面介绍连续求积的方法
SUM()是个求和的聚合函数,如何求积呢?我们可以想办法把乘法变成加法:
A*B*C = 10^(LOG(A)+LOG(B)+LOG(C))
1、直接使用对数和反对数来进行求积,即:LOG和POWER函数
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/dd672ef60563c8e35bfda5d91cd669e4.jpg)
2、使用PL/SQL的自定义函数来实现该功能
SQL:
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/df182034cbf29f2877ccc94df0b27241.jpg)
但是,使用这种方法:newid这个大拿给出了不使用该种方法的建议:
SELECT A*B*C... FROM DUAL;
都是常量且个数不定,每次都需要硬解析,所以不推荐。
下面是tom对使用wm_concat函数的看法:
http://asktom.oracle.com/pls/ask ... #548923200346634568
Hi Tom,
I saw wm_concat on a couple of forums (otn and orafaq), apparently a new, undocumented function as
shown below. Since it is undocumented, is it safe to use?
Regards,
Barbara
Followup November 20, 2007 - 2pm US/Eastern:
my suggestion is going to be consistent....
Never use undocumented stuff, it is subject to change, removal, broken-ness without recourse.
either
a) use stragg
b) write your own
c) use the connect by trick.
3、使用自定义的聚合函数
安德森
函数:
SQL:
结果:
我们在日常的工作中,经常遇到了针对某一列的值,进行求和,求平均值,在一些特殊的业务场景下,我们需要对某一列进行求积操作,那我们该如何实现呢,下面先介绍,我
们对字符串的求和操作。
针对字符串的求和操作:
1、有分隔符的字符串:
SELECT STR, SUM(STR) OVER(ORDER BY LV ASC) AS RS FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR, LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/a4b3dab88ed69042677aff5db1870dff.jpg)
2、没有分割符符号的:
SELECT STR, SUM(STR) OVER(ORDER BY LV ASC) AS RS FROM (SELECT SUBSTR('12345', LEVEL, 1) STR, LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= LENGTH(12345)) COLS
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/17ddb9dcaeacbaf496aeecd2352f53a8.jpg)
下面介绍连续求积的方法
SUM()是个求和的聚合函数,如何求积呢?我们可以想办法把乘法变成加法:
A*B*C = 10^(LOG(A)+LOG(B)+LOG(C))
1、直接使用对数和反对数来进行求积,即:LOG和POWER函数
SELECT STR, POWER(10, SUM(LOG(10, STR)) OVER(ORDER BY STR)) FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR, LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/dd672ef60563c8e35bfda5d91cd669e4.jpg)
2、使用PL/SQL的自定义函数来实现该功能
CREATE OR REPLACE FUNCTION GET_EXPRESSION_RSLT(I_EXPRESSION VARCHAR2) RETURN VARCHAR2 IS /************************************************************ * 函数名称:GET_EXPRESSION_RSLT * 功能描述:获取指定的表达式的结果 * 参数:I_EXPRESSION :表达式 例如:1*2*3 * 编 写 人:XXX * 编写时间:XXXX-XX-XX * 修改记录: *************************************************************/ RETURNSTR VARCHAR2(500) := ''; EXECSQL VARCHAR2(4000) := ''; BEGIN EXECSQL := ' SELECT ' || I_EXPRESSION || ' FROM DUAL'; EXECUTE IMMEDIATE (EXECSQL) INTO RETURNSTR; RETURN RETURNSTR; END;
SQL:
SELECT STR, GET_EXPRESSION_RSLT(REPLACE(WM_CONCAT(STR) OVER(ORDER BY STR), ',', '*')) RS FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR, LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/df182034cbf29f2877ccc94df0b27241.jpg)
但是,使用这种方法:newid这个大拿给出了不使用该种方法的建议:
SELECT A*B*C... FROM DUAL;
都是常量且个数不定,每次都需要硬解析,所以不推荐。
下面是tom对使用wm_concat函数的看法:
http://asktom.oracle.com/pls/ask ... #548923200346634568
Hi Tom,
I saw wm_concat on a couple of forums (otn and orafaq), apparently a new, undocumented function as
shown below. Since it is undocumented, is it safe to use?
Regards,
Barbara
Followup November 20, 2007 - 2pm US/Eastern:
my suggestion is going to be consistent....
Never use undocumented stuff, it is subject to change, removal, broken-ness without recourse.
either
a) use stragg
b) write your own
c) use the connect by trick.
3、使用自定义的聚合函数
安德森
CREATE OR REPLACE TYPE PROD_AGG_TYPE AS OBJECT ( TOTAL NUMBER, STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT PROD_AGG_TYPE) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT PROD_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN PROD_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT PROD_AGG_TYPE, CTX2 IN PROD_AGG_TYPE) RETURN NUMBER ) / CREATE OR REPLACE TYPE BODY PROD_AGG_TYPE IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT PROD_AGG_TYPE) RETURN NUMBER IS BEGIN SCTX := PROD_AGG_TYPE(NULL); SCTX.TOTAL := 1; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT PROD_AGG_TYPE, VALUE IN NUMBER) RETURN NUMBER IS BEGIN SELF.TOTAL := SELF.TOTAL * VALUE; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN PROD_AGG_TYPE, RETURNVALUE OUT NUMBER, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := SELF.TOTAL; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT PROD_AGG_TYPE, CTX2 IN PROD_AGG_TYPE) RETURN NUMBER IS BEGIN SELF.TOTAL := SELF.TOTAL * CTX2.TOTAL; RETURN ODCICONST.SUCCESS; END; END; /
函数:
CREATE OR REPLACE FUNCTION prod_agg(input NUMBER ) RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING prod_agg_type;
SQL:
SELECT STR, prod_agg(STR) OVER(ORDER BY LV ASC) AS RS FROM (SELECT SUBSTR('12345', LEVEL, 1) STR, LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= LENGTH(12345)) COLS
结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/26/72c489c69c5f88a04ce9585ddc11de4e.jpg)
相关文章推荐
- 解决windows phone 7 toolkit中Expanderview点击未展开的可展开列表项题目下边缘空白出现响应的问题
- 解决比较Oracle中CLOB字段问题
- 解决Oracle监听器服务不能启动的问题
- 在Linux中Oracle安装成功后,首次启动使用时,会出现的一些问题总结和解决办法
- 解决oracle临时表空间占满问题
- 解决:[不安装oracle客户端,也要连接oracle服务器]这个问题过程中的经验。
- 探讨PHP获取Oracle数据乱码的相关问题解决办法
- Oracle问题解决记录:报错信息为-ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的 SID
- oracle 锁问题的解决
- 解决System.Data.OracleClient requires Oracle client software version 8.1.7 or greater 问题 续
- rlwrap解决 Oracle sqlplus 在linux 上下文切换乱码问题
- secure crt连接oracle 解决oracle账户锁定问题,并配置weblogic数据源
- 利用NFS挂载盘进行Oracle备份问题的解决
- ORACLE中科学计数法显示问题的解决
- ORACLE EXP/IMP的使用详解 (解决9i(window)导入到10G的乱码问题)
- 解决(Oracle)ORA-12528: TNS: 监听程序: 所有适用例程都无法建立新连接 问题
- PDO取Oracle lob大字段,当数据量太大无法取出的问题的解决办法
- Oracle 8i中字符集乱码问题析及其解决办法
- Oracle之双机热备部署+切换故障问题解决
- 老二牛车Oracle oracle即时客户端Instant Client连接Oracle同时配置解决乱码问题