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
MSMaybe 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 2Hi,
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 -------- BHere 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 adviceHi,
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
; -
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:23Hi,
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 -
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 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
-
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