• Oracle聚合求和和聚合求积(顺便解决BOM展开的问题)


    本文参考网址:http://www.itpub.net/thread-1020772-1-1.html

           我们在日常的工作中,经常遇到了针对某一列的值,进行求和,求平均值,在一些特殊的业务场景下,我们需要对某一列进行求积操作,那我们该如何实现呢,下面先介绍,我

    们对字符串的求和操作。

          针对字符串的求和操作:

         1、有分隔符的字符串:

    1 SELECT STR, SUM(STR) OVER(ORDER BY LV ASC) AS RS
    2   FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR,
    3                LEVEL AS LV
    4           FROM DUAL
    5         CONNECT BY LEVEL <=
    6                    LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS

       结果:
     

    2、没有分割符符号的:

    1       SELECT STR, SUM(STR) OVER(ORDER BY LV ASC) AS RS
    2         FROM (SELECT SUBSTR('12345', LEVEL, 1) STR, LEVEL AS LV
    3                 FROM DUAL
    4               CONNECT BY LEVEL <= LENGTH(12345)) COLS

    结果:

    下面介绍连续求积的方法

    SUM()是个求和的聚合函数,如何求积呢?我们可以想办法把乘法变成加法:

    A*B*C = 10^(LOG(A)+LOG(B)+LOG(C))

    1、直接使用对数和反对数来进行求积,即:LOG和POWER函数

    1 SELECT STR, POWER(10, SUM(LOG(10, STR)) OVER(ORDER BY STR))
    2   FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR,
    3                LEVEL AS LV
    4           FROM DUAL
    5         CONNECT BY LEVEL <=
    6                    LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS

    结果:

    2、使用PL/SQL的自定义函数来实现该功能

     1 CREATE OR REPLACE FUNCTION GET_EXPRESSION_RSLT(I_EXPRESSION VARCHAR2) RETURN VARCHAR2 IS
     2  /************************************************************
     3   * 函数名称:GET_EXPRESSION_RSLT
     4   * 功能描述:获取指定的表达式的结果
     5   * 参数:I_EXPRESSION :表达式  例如:1*2*3
     6   * 编 写 人:XXX
     7   * 编写时间:XXXX-XX-XX
     8   * 修改记录:
     9   *************************************************************/
    10     RETURNSTR VARCHAR2(500) := '';
    11     EXECSQL   VARCHAR2(4000) := '';
    12   BEGIN
    13     EXECSQL := ' SELECT ' || I_EXPRESSION || '  FROM  DUAL';
    14     EXECUTE IMMEDIATE (EXECSQL)
    15       INTO RETURNSTR;
    16     RETURN RETURNSTR;
    17   END;

    SQL:

    1 SELECT STR,
    2        GET_EXPRESSION_RSLT(REPLACE(WM_CONCAT(STR) OVER(ORDER BY STR),
    3                                    ',',
    4                                    '*')) RS
    5   FROM (SELECT REGEXP_SUBSTR('1,2,3,4,5', '[^,]+', 1, LEVEL) AS STR,
    6                LEVEL AS LV
    7           FROM DUAL
    8         CONNECT BY LEVEL <=
    9                    LENGTH(REGEXP_REPLACE('1,2,3,4,5', '[^,]', '')) + 1) COLS

    结果:

    但是,使用这种方法: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、使用自定义的聚合函数

     安德森

     1 CREATE OR REPLACE TYPE PROD_AGG_TYPE AS OBJECT
     2 (
     3   TOTAL NUMBER,
     4 
     5   STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT PROD_AGG_TYPE)
     6     RETURN NUMBER,
     7 
     8   MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF  IN OUT PROD_AGG_TYPE,
     9                                        VALUE IN NUMBER) RETURN NUMBER,
    10 
    11   MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF        IN PROD_AGG_TYPE,
    12                                          RETURNVALUE OUT NUMBER,
    13                                          FLAGS       IN NUMBER)
    14     RETURN NUMBER,
    15 
    16   MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT PROD_AGG_TYPE,
    17                                      CTX2 IN PROD_AGG_TYPE) RETURN NUMBER
    18 )
    19 /
    20 CREATE OR REPLACE TYPE BODY PROD_AGG_TYPE IS
    21 
    22   STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT PROD_AGG_TYPE)
    23     RETURN NUMBER IS
    24   BEGIN
    25     SCTX       := PROD_AGG_TYPE(NULL);
    26     SCTX.TOTAL := 1;
    27     RETURN ODCICONST.SUCCESS;
    28   END;
    29 
    30   MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF  IN OUT PROD_AGG_TYPE,
    31                                        VALUE IN NUMBER) RETURN NUMBER IS
    32   BEGIN
    33     SELF.TOTAL := SELF.TOTAL * VALUE;
    34     RETURN ODCICONST.SUCCESS;
    35   END;
    36 
    37   MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF        IN PROD_AGG_TYPE,
    38                                          RETURNVALUE OUT NUMBER,
    39                                          FLAGS       IN NUMBER) RETURN NUMBER IS
    40   BEGIN
    41     RETURNVALUE := SELF.TOTAL;
    42     RETURN ODCICONST.SUCCESS;
    43   END;
    44 
    45   MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT PROD_AGG_TYPE,
    46                                      CTX2 IN PROD_AGG_TYPE) RETURN NUMBER IS
    47   BEGIN
    48     SELF.TOTAL := SELF.TOTAL * CTX2.TOTAL;
    49     RETURN ODCICONST.SUCCESS;
    50   END;
    51 
    52 END;
    53 /

    函数:

    CREATE OR REPLACE FUNCTION prod_agg(input NUMBER )
    RETURN NUMBER
    PARALLEL_ENABLE AGGREGATE USING prod_agg_type;

    SQL:

    1  SELECT STR, prod_agg(STR) OVER(ORDER BY LV ASC) AS RS
    2         FROM (SELECT SUBSTR('12345', LEVEL, 1) STR, LEVEL AS LV
    3                 FROM DUAL
    4               CONNECT BY LEVEL <= LENGTH(12345)) COLS

    结果:

  • 相关阅读:
    作业5.1 四则运算----封装
    作业四
    作业2 (完)
    作业3
    作业二。。
    数独
    回答自己的提问
    《一个程序猿的生命周期》读后感
    阅读13-17章
    阅读10,11,12章
  • 原文地址:https://www.cnblogs.com/caroline/p/3428324.html
Copyright © 2020-2023  润新知