Analytical function SUM() OVER (PARTITION BY ) in Crosstab

I am trying to resolve this from a very long time. I have an amount column that has to be grouped on Year, but all the other columns grouped by month. I am trying to achieve this using analytic function SUM(Case when (Condition1 and Condition2) then Sum(Amount) else 0 end) OVER ( PARTITION BY Account, Year), Where Account, Sub Account are the left axis columns. Now, column displays the values correctly, but at different rows. This is confusing.............
For Ex: For Account 00001, there are 3 sub accounts 1000,2000,3000. For Sub account 3000, conditions 1 and 2 are satisfied, so it should display the Amount in the row corresponding to Sub account 3000, and 0 for remaining Sub Accounts. And the Total amount of all the sub accounts, which will be the same as amount for SubAccount 3000 should be displayed in the row corresponding to Account 00001.
But I get blank rows for 1000 and 3000 Sub accounts and Amount displayed in 2000 Sub account, and blank for Account 00001 also.
When I created the same workbook in Tabular form, the same amount is displayed for all the SubAccounts of a single Account.
When I used this CASE statement in TOAD, I figured that this is due to the Analytic function. When I use a group by clause as shown below instead of partition by, I get the results I need.
SELECT (Case when (Condition1 and Condition2) then Sum(Amount) else 0 end), Account, Sub Account FROM tables WHERE conditions GROUP BY Year, Account, Sub Account
But I cannot use groupby for whole SQL of the workbook as I need the other columns with page item 'MONTH' not 'Year'.
Could somebody please help me with this?

Hi,
In your tabular form do you get the correct total display against all you subaccounts and account? If this correct then you can use case to ensure that the total is displayed only for the single account.
Once you have the correct totals working in a tabular form it is easier to re-produce what you want in a cross-tab.
Rod West

Similar Messages

  • Case Statement in Analytic Function SUM(n) OVER(PARTITION BY x)

    Hi Guys,
    I have the following SQL that doesn't seem to consider the When clause I am using in the case staement inside the analytic function(SUM). Could somebody let me know why? and suggest the solution?
    Select SUM(Case When (A.Flag = 'B' and B.Status != 'C') Then (NVL(A.Amount_Cr, 0) - (NVL(A.Amount_Dr,0))) Else 0 End) OVER (PARTITION BY A.Period_Year) Annual_amount
         , A.period_year
         , B.status
    , A.Flag
    from A, B, C
    where A.period_year = 2006
    and C.Account = '301010'
    --and B.STATUS != 'C'
    --and A.Flag = 'B'
    and A.Col_x = B.Col_x
    and A.Col_y = C.Col_y
    When I use this SQL, I get
    Annual_Amount Period_Year Status Flag
    5721017.5 --------- 2006 ---------- C -------- B
    5721017.5 --------- 2006 ---------- O -------- B
    5721017.5 --------- 2006 ---------- NULL ----- A
    And when I put the conditions in the where clause, I get
    Annual_Amount Period_Year Status Flag
    5721017.5 ---------- 2006 ---------- O -------- B

    Here are some scripts,
    create table testtable1 ( ColxID number(10), ColyID number(10) , Periodname varchar2(15), Flag varchar2(1), Periodyear number(15), debit number, credit number)
    insert into testtable1 values(1, 1000, 'JAN-06', 'A', 2006, 7555523.71, 7647668)
    insert into testtable1 values(2, 1001, 'FEB-06', 'B', 2006, 112710, 156047)
    insert into testtable1 values(3, 1002, 'MAR-06', 'A', 2006, 200.57, 22376.43)
    insert into testtable1 values(4, 1003, 'APR-06', 'B', 2006, 0, 53846)
    insert into testtable1 values(5, 1004, 'MAY-06', 'A', 2006, 6349227.19, 6650278.03)
    create table testtable2 ( ColxID number(10), Account number(10))
    insert into testtable2 values(1, 300100)
    insert into testtable2 values(2, 300200)
    insert into testtable2 values(3, 300300)
    insert into testtable2 values(4, 300400)
    insert into testtable2 values(5, 300500)
    create table apps.testtable3 ( ColyID number(10), Status varchar2(1))
    insert into testtable3 values(1000, 'C')
    insert into testtable3 values(1001, 'O')
    insert into testtable3 values(1002, 'C')
    My SQL:
    select t1.periodyear
         , SUM(Case When (t1.Flag = 'B' and t3.Status != 'C') Then (NVL(t1.credit, 0) - (NVL(t1.debit,0))) Else 0 End) OVER (PARTITION BY t1.PeriodYear)
         Annual_amount
         , t1.flag
         , t3.status
         , t2.account
    from testtable1 t1, testtable2 t2, testtable3 t3
    where t1.colxid = t2.colxid
    and t1.colyid = t3.colyid(+)
    --and t1.Flag = 'B' and t3.Status != 'C'
    Result:
    PeriodYear ----- AnnualAmount ----- Flag ----- Status ----- Account
    2006 ------------------ 43337 --------------- A ----------- C ---------- 300100
    2006 ------------------ 43337 --------------- B ----------- O ---------- 300200
    2006 ------------------ 43337 --------------- A ----------- C ---------- 300300
    2006 ------------------ 43337 --------------- B ------------ ----------- 300400
    2006 ------------------ 43337 --------------- A ------------ ----------- 300500
    With condition "t1.Flag = 'B' and t3.Status != 'C'" in where clause instead of in Case statement, Result is (which is desired)
    PeriodYear ----- AnnualAmount ----- Flag ----- Status ----- Account
    2006 ------------------ 43337 --------------- B ----------- O ---------- 300200

  • SUM OVER PARTITION BY condition?

    I have a piece of SQL similar to:
    SELECT person,
    amount,
    type,
    SUM(amount) OVER (PARTITION BY person) sum_amount_person
    FROM table_a
    What I would like to be able to do is use a conditional PARTITION BY clause, so rather than partition and summing for each person I would like to be able to sum for each person where type = 'ABC'
    I would expect the syntax to be something like
    SELECT person,
    amount,
    type,
    SUM(amount) OVER (PARTITION BY person WHERE type = 'ABC') sum_amount_person
    FROM table_a
    Is this possible? Or am I missing a much simpler solution?
    Richard

    The proposed query does not compile on my Windows Oracle 9.2.0.5 or 10.1. This could be generated by the ambiguty introduced by DECODE in the evaluation of query (does it filter the selected rows, or the rows summarized for each selected row, or both?).
    I propose two alternatives. The requirements are not specific enough to allow me to choose between them.
    SQL> SELECT * FROM table_a ORDER BY 1, 3;
    PERSON         AMOUNT TYP
    john               12 abc
    john                8 abc
    john               20 def
    mike               15 abc
    mike               30 ghi
    steve              30 abc
    6 rows selected.
    SQL> SELECT person,
      2  amount,
      3  type,
      4  SUM(decode(type, 'ABC',amount, to_number(NULL)) OVER (PARTITION BY person) sum_amount_person
      5  FROM table_a;
    SUM(decode(type, 'ABC',amount, to_number(NULL)) OVER (PARTITION BY person) sum_amount_person
    ERROR at line 4:
    ORA-30483: window  functions are not allowed here
    SQL> SELECT person,
      2  amount,
      3  type,
      4  CASE type WHEN 'abc' THEN SUM(amount) OVER (PARTITION BY person) END sum_amount_person
      5  FROM table_a;
    PERSON         AMOUNT TYP SUM_AMOUNT_PERSON
    john               12 abc                40
    john               20 def
    john                8 abc                40
    mike               15 abc                45
    mike               30 ghi
    steve              30 abc                30
    6 rows selected.
    SQL> SELECT person,
      2  amount,
      3  type,
      4  CASE type WHEN 'abc' THEN SUM(amount) OVER (PARTITION BY person, type) END sum_amount_person
      5  FROM table_a;
    PERSON         AMOUNT TYP SUM_AMOUNT_PERSON
    john               12 abc                20
    john                8 abc                20
    john               20 def
    mike               15 abc                15
    mike               30 ghi
    steve              30 abc                30
    6 rows selected.

  • Analytical function sum() ...for Till-date reporting

    Hi,
    I need help in forming an SQL with analytical function.
    Here is my scenario:
    create table a (name varchar2(10), qty_sold number,on_date date);
    insert into a values ('abc',10,'10-JAN-2007 00:01:00');
    insert into a values ('abc',01,'10-JUL-2007 00:01:00');
    insert into a values ('abc',05,'10-JUL-2007 08:11:00');
    insert into a values ('abc',17,'10-JUL-2007 09:11:00');
    insert into a values ('def',10,'10-JAN-2006 08:01:00');
    insert into a values ('def',01,'10-JUN-2006 10:01:00');
    insert into a values ('def',05,'10-JUL-2006 08:10:00');
    insert into a values ('pqr',17,'10-JUL-2006 09:11:00');
    Now I want to have a sql which displays the following:
    NAME--TOTAL_QTY_SOLD_IN_LAST_10_DAYS, TOTAL_QTY_SOLD_IN_LAST_20_DAYS...etc
    I know we can do it using sum(qty_sold) over (order on_date range interval '10' days and preceding) .... but I get too many rows for each "NAME" ....for each of the date in the database table a ... I want just one row for each "Name"...and sum() should be till SYSDATE ....
    Any help is highly appreciated.
    Thanks.

    SQL> select name
      2       , sum(case when sysdate - on_date <= 10 then qty_sold end) total_qty_last_10_days
      3       , sum(case when sysdate - on_date <= 100 then qty_sold end) total_qty_last_100_days
      4       , sum(case when sysdate - on_date <= 500 then qty_sold end) total_qty_last_500_days
      5    from a
      6   group by name
      7  /
    NAME          TOTAL_QTY_LAST_10_DAYS   TOTAL_QTY_LAST_100_DAYS   TOTAL_QTY_LAST_500_DAYS
    abc                                                         23                        33
    def                                                                                    6
    pqr                                                                                   17
    3 rijen zijn geselecteerd.Regards,
    Rob.

  • PLSQL does not support 'Sum Over Partition'

    I have something (and many obvious syntactical variations) like the following which works great in SQLPLUS but not in PLSQL:
    select
    table1.aField,
    table2.bField,
    sum (table1.type) over (partition by type)
    from
    table1, table2
    where
    aField = something;
    PLSQL does not seem to like the "(" in from of the partition keyword.
    I get the following PL/SQL error when I attempt to compile:
    4/26 PLS-00103: Encountered the symbol "(" when expecting one of the following:
    , from

    What Oracle version are you running?
    Is it Oracle8i?
    Begining with Oracle9i, SQL parsers for SQL and PL/SQL were merged togather. Before 9i, many of the new features introduced in SQL were not recognized by the PL/SQL parser.
    The following example works as expected on Oracle9i:
    SQL> begin
      2    for rec in (select deptno, ename, sum(sal) over (partition by deptno)total  from scott.emp)
      3    loop
      4      dbms_output.put_line(rec.ename||' - '||rec.total) ;
      5    end loop ;
      6  end ;
      7  /
    CLARK - 8750
    KING - 8750
    MILLER - 8750
    SMITH - 10875
    ADAMS - 10875
    FORD - 10875
    SCOTT - 10875
    JONES - 10875
    ALLEN - 9400
    BLAKE - 9400
    MARTIN - 9400
    JAMES - 9400
    TURNER - 9400
    WARD - 9400
    PL/SQL procedure successfully completed.
    SQL> disconnect
    Disconnected from Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production
    With the Partitioning, OLAP and Oracle Data Mining options
    JServer Release 9.2.0.3.0 - Production
    SQL>

  • SUM Over Partition by

    Hi
    I have an calculated field (age_group) which gives month age (0-2Y,2-4Y......)
    I want to sum a measure (which has a sum aggragation rule in the repository) to show the sum of the measure over partition of age_group and the quarter (another dimension).
    when i perform a calculated Item in the request SUM(measure) it gives wrong answers. i want actually to imitate the total option (which is calculated right) in a formula in order to use this formula column in the request
    Any idea how to perform it?
    Thanks

    Hi
    Thanks for your reply
    I will try to explain exactly what i mean:
    I have the following details
    QTR Age_group Money
    2006_Q3 0-2y 10000
    2006_Q3 2-4Y 15000
    2006_Q3 4-6Y 20000
    2006_Q3 more_6 10000
    Total 2006_Q3 55000
    I want to calculate the total and to percent it as new column
    meaning I want a new report that will look like this:
    QTR Age_group Money Money_calc
    2006_Q3 0-2y 10000 55000
    2006_Q3 2-4Y 15000 55000
    2006_Q3 4-6Y 20000 55000
    2006_Q3 more_6 10000 55000
    Thanks

  • How does the analytical function RANK OVER() work inoracle??

    Hi,
    Can i get the information about how oracle internally handles RANK over() ?

    http://tahiti.oracle.com
    http://asktom.oracle.com

  • GROUP BY and analytical functions

    Hi all,
    I need your help with grouping my data.
    Below you can see sample of my data (in my case I have view where data is in almost same format).
    with test_data as(
    select '01' as code, 'SM' as abbreviation, 1010 as groupnum, 21 as pieces, 4.13 as volume, 3.186 as avgvolume from dual
    union
    select '01' as code, 'SM' as abbreviation, 2010 as groupnum, 21 as pieces, 0 as volume, 3.186 as avgvolume from dual
    union
    select '01' as code, 'SM' as abbreviation, 3000 as groupnum, 21 as pieces, 55 as volume, 3.186 as avgvolume from dual
    union
    select '01' as code, 'SM' as abbreviation, 3010 as groupnum, 21 as pieces, 7.77 as volume, 3.186 as avgvolume from dual
    union
    select '02' as code, 'SMP' as abbreviation, 1010 as groupnum, 30 as pieces, 2.99 as volume, 0.1 as avgvolume from dual
    union
    select '03' as code, 'SMC' as abbreviation, 1010 as groupnum, 10 as pieces, 4.59 as volume, 0.459 as avgvolume from dual
    union
    select '40' as code, 'DB' as abbreviation, 1010 as groupnum, 21 as pieces, 5.28 as avgvolume, 0.251 as avgvolume from dual
    select
    DECODE (GROUPING (code), 1, 'report total:', code)     as code,
    abbreviation as abbreviation,
    groupnum as pricelistgrp,
    sum(pieces) as pieces,
    sum(volume) as volume,
    sum(avgvolume) as avgvolume
    --sum(sum(distinct pieces)) over (partition by code,groupnum) as piecessum,
    --sum(volume) volume,
    --round(sum(volume) / 82,3) as avgvolume
    from test_data
    group by grouping sets((code,abbreviation,groupnum,pieces,volume,avgvolume),null)
    order by 1,3;Select statement which I have written returns the output below:
    CODE    ABBR    GRPOUP  PIECES   VOLUME  AVGVOL
    01     SM     1010     21     4.13     3.186
    01     SM     2010     21     0     3.186
    01     SM     3000     21     55     3.186
    01     SM     3010     21     7.77     3.186
    02     SMP     1010     30     2.99     0.1
    03     SMC     1010     10     4.59     0.459
    40     DB     1010     21     5.28     0.251
    report total:          145     79.76     13.554Number of pieces and avg volume is same for same codes (01 - pieces = 21, avgvolume = 3.186 etc.)
    What I need is to get output like below:
    CODE    ABBR    GRPOUP  PIECES   VOLUME  AVGVOL
    01     SM     1010     21     4.13     3.186
    01     SM     2010     21     0     3.186
    01     SM     3000     21     55     3.186
    01     SM     3010     21     7.77     3.186
    02     SMP     1010     30     2.99     0.1
    03     SMC     1010     10     4.59     0.459
    40     DB     1010     21     5.28     0.251
    report total:          82     79.76     0.973Where total number of pieces is computed as sum of distinct numbers of pieces for each code -> *82 = 21 + 30 + 10 +21*.
    Total volume is just sum of volumes in each row -> *79.76 = 4.13+0+55+7.77+2.99+4.59+5.28*.
    And Average volume is computed as total volume / total number of pieces -> *0.973 = 79.76 / 82*.
    I was trying to use analytical function (sum() over (partition by)) to get desired output, but without good results.
    Could anyone help me with this issue?
    Thanks in advance!
    Regards,
    Jiri

    Hi, Jiri,
    Jiri N. wrote:
    Hi all,
    I need your help with grouping my data.
    Below you can see sample of my data (in my case I have view where data is in almost same format).I assume the view guarantees that all rows with the same code (or the same code and groupnum) will always have the same pieces and the same avgvolume.
    with test_data as( ...Thanks for posting this; it's very helpful.
    What I need is to get output like below:
    CODE    ABBR    GRPOUP  PIECES   VOLUME  AVGVOL
    01     SM     1010     21     4.13     3.186
    01     SM     2010     21     0     3.186
    01     SM     3000     21     55     3.186
    01     SM     3010     21     7.77     3.186
    02     SMP     1010     30     2.99     0.1
    03     SMC     1010     10     4.59     0.459
    40     DB     1010     21     5.28     0.251
    report total:          82     79.76     0.973
    Except for the last row, you're just displaying data straight from the table (or view).
    It might be easier to get the results you want uisng a UNION. One branch of the UNION would get the"report total" row, and the other branch would get all the rest.
    >
    Where total number of pieces is computed as sum of distinct numbers of pieces for each code -> *82 = 21 + 30 + 10 +21*.It's not just distinct numbers. In this example, two different codes have pieces=21, so the total of distinct pieces is 61 = 21 + 30 + 10.
    >
    Total volume is just sum of volumes in each row -> *79.76 = 4.13+0+55+7.77+2.99+4.59+5.28*.
    And Average volume is computed as total volume / total number of pieces -> *0.973 = 79.76 / 82*.
    I was trying to use analytical function (sum() over (partition by)) to get desired output, but without good results. I would use nested aggregate functions to do that:
    SELECT    code
    ,       abbreviation
    ,       groupnum          AS pricelistgrp
    ,       pieces
    ,       volume
    ,       avgvolume
    FROM      test_data
         UNION ALL
    SELECT        'report total:'     AS code
    ,        NULL                  AS abbreviaion
    ,        NULL               AS pricelistgrp
    ,        SUM (MAX (pieces))     AS pieces
    ,        SUM (SUM (volume))     AS volume
    ,        SUM (SUM (volume))
          / SUM (MAX (pieces))     AS avgvolume
    FROM        test_data
    GROUP BY   code     -- , abbreviation?
    ORDER BY  code
    ,            pricelistgrp
    ;Output:
    CODE          ABB PRICELISTGRP     PIECES  VOLUME  AVGVOLUME
    01            SM          1010         21    4.13      3.186
    01            SM          2010         21    0.00      3.186
    01            SM          3000         21   55.00      3.186
    01            SM          3010         21    7.77      3.186
    02            SMP         1010         30    2.99       .100
    03            SMC         1010         10    4.59       .459
    40            DB          1010         21    5.28       .251
    report total:                          82   79.76       .973It's unclear if you want to GROUP BY just code (like I did above) or by both code and abbreviation.
    Given that this data is coming from a view, it might be simpler and/or more efficient to make separate version of the view, or to replicate most of the view in a query.

  • HTMLDB 1.6 and "order by" in analytic functions

    In HTMLDB 1.6, oracle 10g, when i enter the string "order by" in the region source of a report of the type "sql query (pl/sql function body returning sql query", I get
    1 error has occurred
    * Your query can't include an "ORDER BY" clause when having column heading sorting enabled.
    I understand the reason for this error, but unfortunately i need this for an analytic function:
    row_number() over (partition by ... order by ...)
    It seems that the check is performed by simply looking for the string "order by" in the "region source" (in fact the error fires even if that string is contained within a comment).
    I know possible workarounds (eg creating a view and select'ing from it), i just wanted to let you know.
    Regards
    Alberto

    Another one under the 'obvious route' category:
    Seems that the ORDER BY check is apparentl for ORDER&lt;space&gt;BY... so simply adding extra whitespace between ORDER and BY bypasses the check (at least in 2.1.0.00.39).
    To make it a bit more obious that a separation is intended, an empty comment, i.e. ORDER/*/BY*, works nicely
    Edited by: mcstock on Nov 19, 2008 10:29 AM

  • How to use sum analytic function in adf

    Hi
    jdev 11.1.1.5
    oracle 11g r2
    I want to use analytic function (sum,count,avg and ...) .
    I see [url http://andrejusb.blogspot.co.uk/2013/02/oracle-analytic-functions-for-total-and.html]Oracle Analytic Functions for Total and Average Calculation in ADF BC
    and use it in my vo and jsf page,my vo have too much record and I want to have sum in table footer on demand (because of performance) and if user do not want to see the sum in footer of table it do not calculate sum,
    what is your idea?

    Before I read that blog I use another vo for sum but after that blog decide to use analytic fuction becuase we have some page that have to many dvt graph and table and know we use seperate vo for them and it has not good performance and too many query must run in database ,I want to have 1 vo with some analytic function for graph and tables

  • Is it possible using Analytical functions?

    Hi,
       I have the following data
        Column1      Column2
        2005            500
        2006            500
        2007            500
        2008            500
    Now, if I've some variable value as 800, then the output record should be
        Column1         Column2
        2008               500
        2007               300
        2006                  0
        2005                  0i.e. the Column2 value(order by column1 desc) is split to accommodate the variable passed.
    Right now, it's being done in PL/SQL. Is it possible to do it in SQL using Analytical function?
    Thanks,
    Sundar
    P.S: It doesnt have to be using analytical, if it can be achieved in a SQL, it's good.
    Message was edited by:
    Sundar M

    Hi, a sample using analytical function SUM:
    CREATE TABLE Source_Data
               ( Year NUMBER
               , Value NUMBER
    BEGIN
       DELETE FROM Source_Data;
       FOR v_Cycle IN 1 .. 6
       LOOP
          INSERT
            INTO Source_Data
                 Year
               , Value
          VALUES
                 2000 + v_Cycle
               , 100 * v_Cycle
       END LOOP;
       COMMIT;
    END;
    VARIABLE v_Amount NUMBER
    EXECUTE :v_Amount := 1200using the SUM, the previous values are totalized:
    so
    SELECT Year
         , Value Year_Value
         , :v_Amount Original_Amount
         , SUM(Value) OVER (ORDER BY Year DESC RANGE UNBOUNDED PRECEDING) Cumulative_Sum
         , DECODE(
                   SIGN(:v_Amount - SUM(Value) OVER (ORDER BY Year DESC RANGE UNBOUNDED PRECEDING))
                   , 1, Value              -- Positive number, more value can be subtract
                   , GREATEST(Value - (SUM(Value) OVER (ORDER BY Year DESC RANGE UNBOUNDED PRECEDING) - :v_Amount), 0)
                 )         Year_Quota
      FROM Source_Data s
    ORDER BY Year DESC
    /will give
         YEAR YEAR_VALUE ORIGINAL_AMOUNT CUMULATIVE_SUM YEAR_QUOTA
         2006        600            1200            600        600
         2005        500            1200           1100        500
         2004        400            1200           1500        100
         2003        300            1200           1800          0
         2002        200            1200           2000          0
         2001        100            1200           2100          0You can add different conditions (PARTITION BY ..)
    Hope this helps
    Max

  • Top n analysis without analytical function or rownum

    Hi
    I am working on Oracle 9i and i have the following query.
    My data is like as
    Year Type Total
    1996 A 23
    1996 B 34
    1996 C 19
    1996 D 11
    1996 E 45
    1996 F 32
    1997 A 12
    1997 B 11
    1997 C 34
    1997 D 45
    1997 E 67
    1997 F 11
    My requirement is to get the top 4 value year wise from the above data. All i need is without the use of ROWNUM as well as other analytical functions like RANK, PARTITION BY etc.
    The required result set is
    Year Type Total
    1996 E 45
    1996 B 34
    1996 F 32
    1996 A 23
    1997 E 67
    1997 D 45
    1997 C 34
    1997 A 12
    Thanks
    MS

    Maybe you can try this:
    SQL> WITH TABLE_A AS
      2  (
      3  SELECT '1996' COL1, 'A' COL2, 23 COL3 FROM DUAL
      4  UNION ALL
      5  SELECT '1996' COL1, 'B' COL2, 34 COL3 FROM DUAL
      6  UNION ALL
      7  SELECT '1996' COL1, 'C' COL2, 19 COL3 FROM DUAL
      8  UNION ALL
      9  SELECT '1996' COL1, 'D' COL2, 11 COL3 FROM DUAL
    10  UNION ALL
    11  SELECT '1996' COL1, 'E' COL2, 45 COL3 FROM DUAL
    12  UNION ALL
    13  SELECT '1996' COL1, 'F' COL2, 32 COL3 FROM DUAL
    14  UNION ALL
    15  SELECT '1997' COL1, 'A' COL2, 12 COL3 FROM DUAL
    16  UNION ALL
    17  SELECT '1997' COL1, 'B' COL2, 11 COL3 FROM DUAL
    18  UNION ALL
    19  SELECT '1997' COL1, 'C' COL2, 34 COL3 FROM DUAL
    20  UNION ALL
    21  SELECT '1997' COL1, 'D' COL2, 45 COL3 FROM DUAL
    22  UNION ALL
    23  SELECT '1997' COL1, 'E' COL2, 67 COL3 FROM DUAL
    24  UNION ALL
    25  SELECT '1997' COL1, 'F' COL2, 11 COL3 FROM DUAL
    26  )
    27  SELECT COL1, COL2, COL3 FROM
    28  (
    29  SELECT
    30  COL1,
    31  COL2,
    32  COL3,
    33  (SELECT COUNT(1) FROM TABLE_A B WHERE A.COL1 = B.COL1 AND B.COL3 > A.COL3) ORDER_NUM
    34  FROM
    35  TABLE_A A
    36  ORDER BY
    37  COL1, COL3 DESC
    38  ) WHERE ORDER_NUM < 4
    39  /
    COL1 C       COL3                                                              
    1996 E         45                                                              
    1996 B         34                                                              
    1996 F         32                                                              
    1996 A         23                                                              
    1997 E         67                                                              
    1997 D         45                                                              
    1997 C         34                                                              
    1997 A         12                                                              

  • Problem with SUM () analytic function

    Dear all,
    Please have a look at my problem.
    SELECT CURR, DT, AMT, RATE,
    SUM(AMT) OVER (PARTITION BY CURR ORDER BY DT) SUMOVER,
    sum( amt * rate) over (PARTITION BY CURR ORDER BY DT) / SUM(AMT) OVER (PARTITION BY CURR ORDER BY DT) avgrt
    FROM
    select 'CHF' CURR, ADD_MONTHS(TO_DATE('01-DEC-07'), LEVEL -1) DT, 100 * LEVEL AMT, 1 +  ( 5* LEVEL/100) RATE
    FROM DUAL CONNECT BY LEVEL < 10
    SQL> /
    CUR DT               AMT       RATE    SUMOVER      AVGRT
    CHF 01-DEC-07        100       1.05        100       1.05
    CHF 01-JAN-08        200        1.1        300 1.08333333
    CHF 01-FEB-08        300       1.15        600 1.11666667
    CHF 01-MAR-08        400        1.2       1000       1.15
    CHF 01-APR-08        500       1.25       1500 1.18333333
    CHF 01-MAY-08        600        1.3       2100 1.21666667
    CHF 01-JUN-08        700       1.35       2800       1.25
    CHF 01-JUL-08        800        1.4       3600 1.28333333
    CHF 01-AUG-08        900       1.45       4500 1.31666667
    Table Revaluation
    select 'CHF' CURR1, '31-DEC-07' DT , 1.08 RATE FROM DUAL UNION ALL
    select 'CHF' CURR1, '31-MAR-08' DT , 1.22 RATE FROM DUAL UNION ALL
    select 'CHF' CURR1, '30-JUN-08' DT , 1.38 RATE FROM DUAL
    CUR DT              RATE
    CHF 31-DEC-07       1.08
    CHF 31-MAR-08       1.22
    CHF 30-JUN-08       1.38.
    Problem is with the calculation of average rate.
    I want to consider the data in the revaluation table to be used in the calculation of
    average rate.
    So average rate for Jan-08 will be
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 ) / (300) = 1.093333333
    for Feb-08
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 + 300 * 1.15) / (600) = 1.121666667
    for mar-08
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 + 300 * 1.15 + 400 * 1.2) / (1000) = 1.153
    for Apr-08
    (1000 * 1.22(Apr revaluation rate) + 500 * 1.25) /1500 = 1.23
    for May-08
    (1000 * 1.22(Apr revaluation rate) + 500 * 1.25 + 600 * 1.30 ) /2100 = 1.25
    and so on..
    Kindly advice

    Hi,
    The main thing in this problem is that for every dt you want to compute the cumulative total from previous rows using the formula
    SUM (amt * rate)
    But rate can be either the rate from the revaluation table or the rate from the main table. For evaluating prior dates, you wnat to use the most recent rate.
    I'm not sure if you can do this using analytic functions. Like Damorgan said, you should use a self-join.
    The query below gives you the results you requested:
    WITH
    revaluation     AS
         SELECT 'CHF' curr1, TO_DATE ('31-DEC-07', 'DD-MON-RR') dt, 1.08 rate     FROM dual     UNION ALL
         SELECT 'CHF' curr1, TO_DATE ('31-MAR-08', 'DD-MON-RR') dt, 1.22 rate     FROM dual     UNION ALL
         SELECT 'CHF' curr1, TO_DATE ('30-JUN-08', 'DD-MON-RR') dt, 1.38 rate     FROM dual
    original_data     AS
         select     'CHF'                              curr
         ,     ADD_MONTHS(TO_DATE('01-DEC-07'), LEVEL -1)     dt
         ,     100 * LEVEL                         amt
         ,     1 + ( 5* LEVEL/100)                    rate
         FROM     dual
         CONNECT BY     LEVEL < 10
    two_rates     AS
         SELECT     od.*
              SELECT     MAX (dt)
              FROM     revaluation
              WHERE     curr1     = od.curr
              AND     dt     <= od.dt
              )          AS r_dt
              SELECT     AVG (rate) KEEP (DENSE_RANK LAST ORDER BY dt)
              FROM     revaluation
              WHERE     curr1     = od.curr
              AND     dt     <= od.dt
              )          AS r_rate
         FROM     original_data     od
    SELECT     c.curr
    ,     c.dt
    ,     c.amt
    ,     c.rate
    ,     SUM (p.amt)          AS sumover
    ,     SUM     ( p.amt
              * CASE
                   WHEN     p.dt <= c.r_dt
                   THEN     c.r_rate
                   ELSE     p.rate
                END
         / SUM (p.amt)          AS avgrt
    FROM     two_rates     c
    JOIN     original_data     p     ON     c.curr     = p.curr
                        AND     c.dt     >= p.dt
    GROUP BY     c.curr,     c.dt,     c.amt,     c.rate
    ORDER BY     c.curr,     c.dt
    ;

  • Sum Analytic Function

    Hi,
    I have a query in SQL that generates percentage totals. I am having trouble replicating this code in BMM layer of the repository. I have created a new logical column, the sql query is below:
    SELECT id, seq, asset_cost ,
    CASE
    WHEN asset_cost > 0
    THEN ROUND(RATIO_TO_REPORT (
    CASE
    WHEN asset_cost > 0
    THEN SUM (asset_cost)
    END) OVER (partition BY id)*100)
    END total
    FROM test
    GROUP BY id, seq asset_cost
    Can anyone help with replicating the above expression in the logical layer column. ]
    *** how can i use the Ratio_to_report function in obiee
    The above link shows a workaround
    Are there any alternatives to 'RATIO_TO_REPORT' in OBIEE functions?
    Thanks
    Edited by: sliderrules on 16-May-2012 04:23

    Hi,
    I have just been through the Oracle documentation to understand that 'RATIO_TO_REPORT' would compute the ratio of a value to sum of values. For your requirement, what you could do is
    1. Bring in the measure 'asset_cost' into the BMM with aggregation rule as sum. (I think you could include a condition here itself as asset_cost >0)
    2. Create another measure with the 'Derived from another logical column as source' option chosen and the function as
    EVALUATE('RATIO_TO_REPORT(%1) OVER (PARTITION BY %2)' AS DOUBLE, asset_cost,id)
    The above function does the following steps:
    EVALUATE will send the analytic function to the database.
    SUM(asset_cost) would be the first parameter
    id would be the second parameter.
    I might not be pretty good with the syntax here, but hope you could get it while implementing.
    Hope this helps.
    Thank you,
    Dhar

  • SUM analytical function

    Hi,
    I am using the SUM analytical function to accumulate some data from one record to the other record (data per month):
    TPS_MOI_CODE     PRD_PRD_CODE     PDV_PDV_CODE     RTTCAVCANV
    200510     01     9302     -8050
    200511     01     9302     -15500
    200512     01     9302     -16150
    200601     01     9302     -16150
    200602     01     9302     -16150
    200603     01     9302     -16150
    The result is correct. However, I also want to restart the sum from January, i.e every months contain the sum of all the previous month, and it must restart in January.
    How do I do that ?
    Thanks in advance for your answers.

    You should extract a year and use it as the partition in over() clause, for example:
    SQL> select * from t;
         DATE#        QTY
        200510          1
        200511          2
        200512          3
        200601          4
        200602          5
        200603          6
    6 rows selected.
    SQL> desc t;
    Name                                      Null?    Type
    DATE#                                              NUMBER
    QTY                                                NUMBER
    SQL> select date#, sum(qty) over(partition by substr(date#,1,4) order by date#) cum_sum
      2  from t;
         DATE#    CUM_SUM
        200510          1
        200511          3
        200512          6
        200601          4
        200602          9
        200603         15
    6 rows selected.Rgds.

Maybe you are looking for