Running Sum without analytic function

Hi
I have data like below
Create table Test (Name Varchar(30),M Int, Y Int, Val Int);
Insert into Test Values ('A',1,2011,2);
Insert into Test Values ('A',2,2011,2);
Insert into Test Values ('A',3,2011,2);
Insert into Test Values ('A',4,2011,2);
Insert into Test Values ('A',5,2011,2);
Insert into Test Values ('A',6,2011,2);
Insert into Test Values ('A',7,2011,2);
Insert into Test Values ('A',8,2011,2);
Insert into Test Values ('A',9,2011,2);
Insert into Test Values ('A',10,2011,2);
Insert into Test Values ('A',11,2011,2);
Insert into Test Values ('A',12,2011,2);
Insert into Test Values ('A',1,2012,2);
Insert into Test Values ('A',2,2012,2);
Insert into Test Values ('A',3,2012,2);
Insert into Test Values ('A',4,2012,2);
Insert into Test Values ('A',5,2012,2);
Insert into Test Values ('A',6,2012,2);
Insert into Test Values ('A',7,2012,2);
Now based on above data I need to calculate running sum for past 18 Months. Condition is I can not use analytic function or Oracle specific SQL functions (for portability).
I tries following SQL but it dint work
select Name,rnk, SUM(val) from (
SELECT a.Name,a.m,a.Y,b.val, count(*) rnk
from Test a, Test b
where (a.Name=b.Name and (a.M <= b.M and a.Y<= b.Y))
group by a.Name,a.Y,a.m
order by a.Name,a.Y,a.m
) abc
group By Name,rnk
Order by Name,rnk
Can some one give suggastion.

Hi,
I don't see what your query or your desired results have to do with the last 18 months. Is the task here to show for a given month (July, 2012, for example) the total of the 18 months ending in that month (February, 2011 through July, 2012 in this case) for the same name? If so:
SELECT       c.name, c.y, c.m
,       SUM (p.val)     AS running_total
FROM       test     c
JOIN       test     p  ON     ( ((12 * c.y) + c.m)
               - ((12 * p.y) + p.m)
               ) BETWEEN 0 AND 17
GROUP BY  c.name, c.y, c.m
ORDER BY  c.name, c.y, c.m
;Output:
NAME                Y          M RUNNING_TOTAL
A                2011          1             2
A                2011          2             4
A                2011          3             6
A                2011          4             8
A                2011          5            10
A                2011          6            12
A                2011          7            14
A                2011          8            16
A                2011          9            18
A                2011         10            20
A                2011         11            22
A                2011         12            24
A                2012          1            26
A                2012          2            28
A                2012          3            30
A                2012          4            32
A                2012          5            34
A                2012          6            36
A                2012          7            36

Similar Messages

  • 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                                                              

  • Forms 10g not supporting Analytical functions

    Hi all
    i try to use analytic funtion like
         row_number() over (partition by uuid order by timesheet_acct) rn
    but form did not compile this while when i run the same analytic function in SQL prompt it runs fine. is forms support Analytical functions?? if not then what can i do for performing this task at form??
    thx.

    Ok, so look at this stored function:
    CREATE OR REPLACE FUNCTION Return_Cursor
      PC$Select IN VARCHAR2
    ) RETURN SYS_REFCURSOR
    IS
      cc  SYS_REFCURSOR ;
    BEGIN
      OPEN cc FOR PC$Select ;
      RETURN cc ;
    END ;
    /Then imagine you can call it with ANY query like the following:
    SQL> set serveroutput on
    SQL> DECLARE
      2     cur SYS_REFCURSOR ;
      3     CURSOR c IS SELECT deptno, ename, sal FROM EMP ;
      4     rec c%ROWTYPE ;
      5     LC$Req  VARCHAR2(2000) ;  
      6    BEGIN
      7      LC$Req := 'SELECT deptno, ename, sal FROM ' ;
      8      LC$Req := LC$Req || '(SELECT deptno, ename, sal, row_number() over ' ;
      9      LC$Req := LC$Req || '(PARTITION BY deptno ORDER BY sal DESC) FROM EMP ORDER BY deptno, sal)' ;
    10      cur := Return_Cursor( LC$Req ) ;
    11      LOOP
    12        FETCH cur INTO rec ;
    13        EXIT WHEN cur%NOTFOUND ;
    14        dbms_output.put_line( rec.DEPTNO || '  ' || rec.ENAME || ' -> ' || rec.SAL ) ;
    15      END LOOP ;
    16      CLOSE cur ;
    17  END;
    18  /
    10  MILLER -> 1301
    10  CLARK -> 2450
    10  KING -> 5000
    20  SMITH -> 915
    20  ADAMS -> 1100
    20  JONES -> 2975
    20  SCOTT -> 3000
    20  FORD -> 3000
    30  JAMES -> 950
    30  WARD -> 1250
    30  MARTIN -> 1250
    30  TURNER -> 1500
    30  ALLEN -> 1600
    30  BLAKE -> 2850
    Procédure PL/SQL terminée avec succès.What do you think ?
    Francois

  • Alternate for analytic functions

    Hello All,
    I'm trying to write a query without using analytic functions.
    Using Analytic func,
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    PL/SQL Release 11.2.0.2.0 - Production
    "CORE     11.2.0.2.0     Production"
    TNS for Linux: Version 11.2.0.2.0 - Production
    NLSRTL Version 11.2.0.2.0 - Production
    SELECT id, sal, rank() OVER (PARTITION BY ID ORDER BY SAL) rnk FROM
    (SELECT 10 AS id, 100 AS sal FROM DUAL
        UNION ALL
        SELECT 10, 300 FROM DUAL
        UNION ALL
        SELECT 10, 400 FROM DUAL
        UNION ALL
        SELECT 20, 200 FROM DUAL
        UNION ALL
        SELECT 20, 200 FROM DUAL
        UNION ALL
        SELECT 20, 300 FROM DUAL
        UNION ALL
        SELECT 30, 100 FROM DUAL
        UNION ALL
        SELECT 40, 100 FROM DUAL
        UNION ALL
        SELECT 40, 200 FROM DUAL
        ) Expected results. I want these results without analytic functions.
    10     100     1
    10     300     2
    10     400     3
    20     200     1
    20     200     1
    20     300     3
    30     100     1
    40     100     1
    40     200     2

    Hi,
    SamFisher wrote:
    Thank You Frank. That was simple.
    I was trying to get the reults without using analytical functions. Just trying to improve my SQL skills. Yes, I admit that practicising using the wrong tools can improve your SQL skills, but I think there's a lot to be said for practising using the right tools, too.
    I tried all sort of things. I thought hierarchical query would do it but hard luck for me.Do you want to use a CONNECT BY query for this? Here's one way:
    WITH     got_max_level            AS
         SELECT       id
         ,       sal
         ,       MAX (LEVEL)     AS max_level
         FROM       table_x
         CONNECT BY NOCYCLE  id        = PRIOR id
              AND          sal       >= PRIOR sal
              AND     (   sal       >  PRIOR sal
                   OR  ROWID > PRIOR ROWID
         GROUP BY  id
         ,            sal
    ,     got_cnt          AS
         SELECT       id
         ,       sal
         ,       COUNT (*)     AS cnt
         FROM       table_x
         GROUP BY  id
         ,            sal
    SELECT       x.id
    ,       x.sal
    ,       l.max_level + 1 - c.cnt     AS rnk
    FROM       table_x        x
    JOIN       got_max_level  l  ON   x.id     = l.id
                         AND      x.sal     = l.sal
    JOIN       got_cnt      c  ON      x.id     = c.id
                         AND      x.sal     = c.sal
    ORDER BY  x.id
    ,            x.sal
    ;This is even less efficient, as well as more complicated, than the scalar sub-query solution.

  • Advantages and disadvantages of Analytical function

    Plz list out the advantages and disadvantages of normal queries and queries using analytical function (Performance wise)

    I'm not sure how you wish to compare?
    Analytical functions give you functionality that cannot otherwise be achieved easily in a lot of cases. They can introduce some performance degredation to a query but you have to compare on a query by query basis to determine if analytical functions or otherwise are the best solution for the issue. If it were as simple as saying that analytical functions are always slower than doing it without analytical functions, then Oracle wouldn't bother introducing them into the language.

  • 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

  • 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

  • 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

  • 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

  • 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.

  • 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.

  • Analytic Functions with GROUP-BY Clause?

    I'm just getting acquainted with analytical functions. I like them. I'm having a problem, though. I want to sum up the results, but either I'm running into a limitation or I'm writing the SQL wrong. Any hints for me?
    Hypothetical Table SALES consisting of a DAY_ID, PRODUCT_ID, PURCHASER_ID, PURCHASE_PRICE lists all the
    Hypothetical Business Question: Product prices can fluctuate over the course of a day. I want to know how much per day I would have made had I sold one each of all my products at their max price for that day. Silly question, I know, but it's the best I could come up with to show the problem.
    INSERT INTO SALES VALUES(1,1,1,1.0);
    INSERT INTO SALES VALUES(1,1,1,2.0);
    INSERT INTO SALES VALUES(1,2,1,3.0);
    INSERT INTO SALES VALUES(1,2,1,4.0);
    INSERT INTO SALES VALUES(2,1,1,5.0);
    INSERT INTO SALES VALUES(2,1,1,6.0);
    INSERT INTO SALES VALUES(2,2,1,7.0);
    INSERT INTO SALES VALUES(2,2,1,8.0);
    COMMIT;
    Day 1: Iif I had sold one product 1 at $2 and one product 2 at $4, I would have made 6$.
    Day 2: Iif I had sold one product 1 at $6 and one product 2 at $8, I would have made 14$.
    The desired result set is:
    DAY_ID                 MY_MEASURE
    1                        6
    1                       14The following SQL gets me tantalizingly close:
    SELECT DAY_ID,
      MAX(PURCHASE_PRICE)
      KEEP(DENSE_RANK FIRST ORDER BY PURCHASE_PRICE DESC)
      OVER(PARTITION BY DAY_ID, PRODUCT_ID) AS MY_MEASURE
      FROM SALES
    ORDER BY DAY_ID
    DAY_ID                 MY_MEASURE
    1                      2
    1                      2
    1                      4
    1                      4
    2                      6
    2                      6
    2                      8
    2                      8But as you can see, my result set is "longer" than I wanted it to be. I want a single row per DAY_ID. I understand what the analytical functions are doing here, and I acknowledge that I am "not doing it right." I just can't seem to figure out how to make it work.
    Trying to do a sum() of max() simply does not work, nor does any semblance of a group-by clause that I can come up with. Unfortunately, as soon as I add the windowing function, I am no longer allowed to use group-by expressions (I think).
    I am using a reporting tool, so unfortunately using things like inline views are not an option. I need to be able to define "MY_MEASURE" as something the query tool can apply the SUM() function to in its generated SQL.
    (Note: The actual problem is slightly less easy to conceptualize, but solving this conundrum will take me much closer to solving the other.)
    I humbly solicit your collective wisdom, oh forum.

    Thanks, SY. I went that way originally too. Unfortunately that's no different from what I could get without the RANK function.
    SELECT  DAY_ID,
            PRODUCT_ID,
            MAX(PURCHASE_PRICE) MAX_PRICE
      FROM  SALES
      GROUP BY DAY_ID,
               PRODUCT_ID
      ORDER BY DAY_ID,
               PRODUCT_ID
    DAY_ID                 PRODUCT_ID             MAX_PRICE             
    1                      1                      2                     
    1                      2                      4                     
    2                      1                      6                     
    2                      2                      8

  • Discoverer Analytic Function windowing - errors and bad aggregation

    I posted this first on Database General forum, but then I found this was the place to put it:
    Hi, I'm using this kind of windowing function:
    SUM(Receitas Especificas) OVER(PARTITION BY Tipo Periodo,Calculado,"Empresa Descrição (Operador)","Empresa Descrição" ORDER BY Ini Periodo RANGE BETWEEN INTERVAL '12' MONTH PRECEDING AND INTERVAL '12' MONTH PRECEDING )
    If I use the "Receitas Especificas SUM" instead of
    "Receitas Especificas" I get the following error running the report:
    "an error occurred while attempting to run..."
    This is not in accordance to:
    http://www.boku.ac.at/oradoc/ias/10g(9.0.4)/bi.904/b10268.pdf
    but ok, the version without SUM inside works.
    Another problem is the fact that for analytic function with PARTITION BY,
    this does not work (shows the cannot aggregate symbol) if we collapse or use "<All>" in page items.
    But it works if we remove the item from the PARTITION BY and also remove from workbook.
    It's even worse for windowing functions(query above), because the query
    only works if we remove the item from the PARTITION BY but we have to show it on the workbook - and this MAKES NO SENSE... :(
    Please help.

    Unfortunately Discoverer doesn't show (correct) values for analytical functions when selecting "<All>" in a page item. I found out that it does work when you add the analytical function to the db-view instead of to the report as a calculation or as a calculated item on the folder.
    The only problem is you've to name all page-items in the PARTITION window, so, when adding a page-item to the report, you,ve to change the db-view and alter the PARTITION window.
    Michael

  • [8i] Subquery vs Multiple Analytic Functions

    Does anyone have an idea which is better performance-wise?
    I have a query that is 3 layers deep already with sub-queries. In the topmost level, I have a choice. I can calculate one analytic function twice, and one analytic function three times, or I can make the topmost level into a subquery, and calculate each analytic function only once.
    In case it matters for this problem, this query is running on an 8i database.
    A simplified example:
    CREATE TABLE     my_data
    (     order_no     CHAR(10)
    ,     seq_nbr          CHAR(4)
    ,     area_id          CHAR(4)
    ,     start_date     DATE
    ,     unit_time     NUMBER(7,2)
    INSERT INTO my_data VALUES ('0000567890','0010','A001',TO_DATE('05/01/2000','mm/dd/yyyy'),0.34);
    INSERT INTO my_data VALUES ('0000567890','0020','A001',TO_DATE('05/02/2000','mm/dd/yyyy'),0.78);
    INSERT INTO my_data VALUES ('0000567890','0030','A002',TO_DATE('05/03/2000','mm/dd/yyyy'),0.91);
    INSERT INTO my_data VALUES ('0000567890','0040','A003',TO_DATE('05/03/2000','mm/dd/yyyy'),0.27);
    INSERT INTO my_data VALUES ('0000123456','0010','A001',TO_DATE('04/01/2001','mm/dd/yyyy'),0.39);
    INSERT INTO my_data VALUES ('0000123456','0020','A001',TO_DATE('04/02/2001','mm/dd/yyyy'),0.98);
    INSERT INTO my_data VALUES ('0000123456','0030','A002',TO_DATE('04/03/2001','mm/dd/yyyy'),0.77);
    INSERT INTO my_data VALUES ('0000123456','0040','A003',TO_DATE('04/03/2001','mm/dd/yyyy'),0.28);
    INSERT INTO my_data VALUES ('0000123123','0010','A001',TO_DATE('12/01/2001','mm/dd/yyyy'),0.31);
    INSERT INTO my_data VALUES ('0000123123','0020','A001',TO_DATE('12/02/2001','mm/dd/yyyy'),0.86);
    INSERT INTO my_data VALUES ('0000123123','0030','A002',TO_DATE('12/03/2001','mm/dd/yyyy'),0.82);
    INSERT INTO my_data VALUES ('0000123123','0040','A003',TO_DATE('12/03/2001','mm/dd/yyyy'),0.23);
    INSERT INTO my_data VALUES ('0000111111','0010','A001',TO_DATE('06/01/2002','mm/dd/yyyy'),0.29);
    INSERT INTO my_data VALUES ('0000111111','0020','A001',TO_DATE('06/02/2002','mm/dd/yyyy'),0.84);
    INSERT INTO my_data VALUES ('0000111111','0030','A002',TO_DATE('06/03/2002','mm/dd/yyyy'),0.78);
    INSERT INTO my_data VALUES ('0000111111','0040','A003',TO_DATE('06/03/2002','mm/dd/yyyy'),0.26);
    INSERT INTO my_data VALUES ('0000654321','0010','A001',TO_DATE('05/01/2003','mm/dd/yyyy'),0.28);
    INSERT INTO my_data VALUES ('0000654321','0020','A001',TO_DATE('05/02/2003','mm/dd/yyyy'),0.88);
    INSERT INTO my_data VALUES ('0000654321','0030','A002',TO_DATE('05/03/2003','mm/dd/yyyy'),0.75);
    INSERT INTO my_data VALUES ('0000654321','0040','A003',TO_DATE('05/03/2003','mm/dd/yyyy'),0.25);My choices for the example are:
    SELECT     area_id
    ,     period_start
    ,     period_end
    ,     AVG(tot_area_unit_hrs)     
         OVER     (
              PARTITION BY     area_id
              ORDER BY     period_start
              RANGE BETWEEN     period_end - period_start     PRECEDING
                    AND     CURRENT ROW
         STDDEV(tot_area_unit_hrs)     
         OVER     (
              PARTITION BY     area_id
              ORDER BY     period_start
              RANGE BETWEEN     period_end - period_start     PRECEDING
                    AND     CURRENT ROW
              )           AS lo_unit_time
    ,     AVG(tot_area_unit_hrs)     
         OVER     (
              PARTITION BY     area_id
              ORDER BY     period_start
              RANGE BETWEEN     period_end - period_start     PRECEDING
                    AND     CURRENT ROW
              )               AS avg_unit_time
    ,     AVG(tot_area_unit_hrs)     
         OVER     (
              PARTITION BY     area_id
              ORDER BY     period_start
              RANGE BETWEEN     period_end - period_start     PRECEDING
                    AND     CURRENT ROW
              )               +
         STDDEV(tot_area_unit_hrs)     
         OVER     (
              PARTITION BY     area_id
              ORDER BY     period_start
              RANGE BETWEEN     period_end - period_start     PRECEDING
                    AND     CURRENT ROW
              )           AS hi_unit_time
    FROM     (
         SELECT     order_no
         ,     area_id
         ,     ADD_MONTHS(MIN(start_date),-24)+1     AS period_start
         ,     MIN(start_date)                    AS period_end
         ,     SUM(unit_time)                    AS tot_area_unit_hrs
         FROM     my_data
         GROUP BY     order_no
         ,          area_id
    ORDER BY     area_id
    ,          period_end
    ;or
    SELECT     area_id
    ,     period_start
    ,     period_end
    ,     avg_unit_time - stdev_unit_time     AS lo_unit_time
    ,     avg_unit_time
    ,     avg_unit_time + stdev_unit_time     AS hi_unit_time
    FROM     (
         SELECT     area_id
         ,     period_start
         ,     period_end
         ,     STDDEV(tot_area_unit_hrs)     
              OVER     (
                   PARTITION BY     area_id
                   ORDER BY     period_start
                   RANGE BETWEEN     period_end - period_start     PRECEDING
                         AND     CURRENT ROW
                   )           AS stdev_unit_time
         ,     AVG(tot_area_unit_hrs)     
              OVER     (
                   PARTITION BY     area_id
                   ORDER BY     period_start
                   RANGE BETWEEN     period_end - period_start     PRECEDING
                         AND     CURRENT ROW
                   )               AS avg_unit_time
         FROM     (
              SELECT     order_no
              ,     area_id
              ,     ADD_MONTHS(MIN(start_date),-24)+1     AS period_start
              ,     MIN(start_date)                    AS period_end
              ,     SUM(unit_time)                    AS tot_area_unit_hrs
              FROM     my_data
              GROUP BY     order_no
              ,          area_id
    ORDER BY     area_id
    ,          period_end
    ;My gut instinct would be that the 2nd option is faster (with the sub-query), but before I try this on my actual data set which is much larger, I'd like a second opinion. I don't want to accidentally start running a "neverending" query.

    Sorry for the delay in response here... I was busy deleting 39 GB of trace files, because some silly person (hangs head in shame) accidentally set TRACE_LEVEL_CLIENT=SUPPORT months ago and forgot to turn it off, and didn't notice until her hard drive was full and she couldn't save a file.....
    Anyway...
    @Dev
    For the real query...
    option 1 explain plan:
    OPERATION          OPTIONS          OBJECT_NODE   OBJECT_OWNER   OBJECT_NAME   OBJECT_INSTANCE   OBJECT_TYPE   OPTIMIZER      ID   PARENT_ID   POSITION   COST   CARDINALITY   BYTES    
    SELECT STATEMENT   REMOTE                                                                                      HINT: CHOOSE   0                6076       6076   1             91       
    SORT               ORDER BY                                                                                                   1    0           1          6076   1             91       
    WINDOW             SORT                                                                                                       2    1           1                 1             91       
    SORT               GROUP BY                                                                                                   3    2           1          6076   1             91       
    FILTER                                                                                                                        4    3           1                                        
    NESTED LOOPS                                                                                                                  5    4           1          6071   1             91       
    TABLE ACCESS       FULL             DB8I.WORLD    ASCHEMA        DETAILS       2                                              6    5           1          6068   1             50       
    INDEX              RANGE SCAN       DB8I.WORLD    ASCHEMA        ORDERS_IX3                      UNIQUE        ANALYZED       7    5           2          3      141930        5819130  
    TABLE ACCESS       BY INDEX ROWID   DB8I.WORLD    ASCHEMA        DETAILS       3                                              8    4           2          7      1             44       
    INDEX              RANGE SCAN       DB8I.WORLD    ASCHEMA        DETAILS_IX1                     NON-UNIQUE    ANALYZED       9    8           1          3      1                       option 2 explain plan:
    OPERATION          OPTIONS    OBJECT_NODE   OBJECT_OWNER   OBJECT_NAME   OBJECT_INSTANCE   OBJECT_TYPE   OPTIMIZER      ID   PARENT_ID   POSITION   COST   CARDINALITY   BYTES  
    SELECT STATEMENT                                                                                         HINT: CHOOSE   0                2777       2777   96            14208  
    SORT               ORDER BY                                                                                             1    0           1          2777   96            14208  
    VIEW                                        LOCALUSER                    1                                              2    1           1          2776   96            14208  
    WINDOW             SORT                                                                                                 3    2           1          2776   96            26400  
    HASH               GROUP BY                                                                                             4    3           1          2776   96            26400  
    FILTER                                                                                                                  5    4           1                                      
    REMOTE                        DB8I                                                         REMOTE                       6    5           1          1908   386           59830  
    REMOTE                        DB8I                         DETAILS                         REMOTE                       7    5           2          4      1             129     You should know, in order to get explain plan on these queries, I have to run them via a database link to the 8i database through XE 10g on my local machine, as I don't have access to run explain plan on the remote database itself. I've never seen my local user name appear before in an explain plan run this way, but it did in the one for option #2 (subquery), so I'd guess that wouldn't be the explain plan I'd get if I ran it just in the 8i database. I also find it really odd that the ORDERS table doesn't seem to be referenced in the 2nd explain plan... I do think that's still going to be my best option though, so I'm going to try it and hope it doesn't take too long.
    @Frank Kulash
    Agreed. That's what I'll try, and I also think that I can't put the analytic function in with the aggregates, without having to do some additional computations in that sub-query, which I think would defeat the purpose of putting them there in the first place.

Maybe you are looking for

  • I installed a new wifi router and airport will not connect automatically to it. It sees the network but will not connect unless I tell it to.

    I installed a new wifi router and airport will not connect automatically to it. It sees the network but will not connect unless I tell it to. I can't find anywhere in the utility or network preferences that will allow me to choose this router as the

  • Maximize.... Frustration

    Ok, I have been a Mac user for a long time, and I know that the green + button resizes the window... but... here is what really grinds my gears... Why doesn't it, when toggled, force the window to fit the screen. People say, size the window first the

  • Does the TM create a sparse bundle on a Raid 5 device with a local thunderbolt connection

    I know that TM creates a sparse bundle when used over a network connection.  I would like to know if also creates a sparse bundle on a raid  device ( Lacie 5 big thunderbolt 2) which is connected locally, and formatted in HFS+.  The reason I'm asking

  • Fcode in Selection-screen

    Hi experts, I have a Report with selection-screen. How can I catch the fcode when press f8 or f3 or any funktion button. Normally it is in sy-ucomm but when I push after showing alv or list it comes to initialization and sy-ucomm ist empty. is there

  • Reporting-Top 10 and Rank() function

    Need to modify Top 10 Opportunities Pre-defined analysis report. In doing so, we loose the drop down Fiscal Qtr/Year. The only option is to create a Pivot table, and use Fiscal Qtr/Year as a selector. The issue is that I need to be able to retrieve t