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 -------- 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 -
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?
RichardThe 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:
, fromWhat 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> -
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?
ThanksHi
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,
JiriHi, 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
AlbertoAnother one under the 'obvious route' category:
Seems that the ORDER BY check is apparentl for ORDER<space>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 MHi, 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
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 -
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 -
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
-
If I try to update or restore it, a message pops up saying, "The Ipod software update server could not be contacted. Make sure your network settings are correct and your network connection is active, or try again later." How can I fix this? I really
-
Can anyone please tell me - ( I have spent many hours on the apple website looking for contact details of a real person; but no good )- what to do with my IPod Nano screen that does not work. It is not cracked but is very bright, unreadable and seems
-
Is there a way to prevent iPhone apps from syncing to my iPad?
Whenever I install a new app on my iPhone, it gets synced to my iPad even though it's an iPhone-only app. Is there a way to restrict my iPad to only receive apps designed for iPad upon sync?
-
The question above says it all. I tried to purchase a season pass for a tv show, but, I can't because I don't have enough space on my phone. I have a 16gb iPhone 4S (I already know how to make more space on my phone). I have 10.9gb's available. But,
-
Help With Elements 11 . . .
When I open a photo in Elements 11 and click on the "Expert" tab at the top, the options in the right hand margin have changed from "Touchups" to something entirely different. How do I get the "Touchups" options to appear on the "Expert" tab. Thanks.