| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> c.d.o.misc -> Re: Analytic function insight wanted
Charles Hooper schrieb:
> On Mar 2, 10:07 pm, y..._at_vtn1.victoria.tc.ca (Malcolm Dew-Jones)
> wrote:
>> Hello
>>
>> I am looking for some insight on solving this problem using analytic
>> functions.
>>
>> I already have another, non-analytic, solution, but I am not happy with it
>> because it seems overly complicated. As a procedure I am sure I could
>> just scan once thru the sorted data, so it seems "obvious" that I should
>> be able to find an easy elegant solution to this in SQL, and I think that
>> analytic functions would do that, but I just can't think how to use them
>> here.
>>
>> I have a table like this (simplified version shown here).
>>
>> year category value1
>> ---- -------- ------
>>
>> 2000 A1 1
>> 2000 A2 10
>> 2000 B1 2
>> 2000 B2 20
>> 2000 C 50
>>
>> 2001 A1 3
>> 2001 B1 4
>>
>> 2002 A2 60
>> 2002 B1 8
>> 2002 C 7
>>
>> I show a kind of rollup with three categories, each being the sum of the
>> two most recently available values for each year. A key issue being that
>> the value for a year may be missing and so you need to use the most recent
>> value from the past. A complication is that the final value for a year is
>> actually the sum of two values, each of which may be from different
>> previous years. (One column is not a sum so I show that just in case it
>> makes a difference.)
>>
>> (The "+" is just to illustrate the numbers involved, the actual value is
>> the mathematic sum of the numbers.)
>>
>> year sum(a1+a2) sum(b1+b2) C
>> ---- ---------- ---------- -
>> 2000 1+10 2+20 50
>> 2001 3+10 4+20 50
>> 2002 3+60 8+20 7
>>
>> Right now I use a partial cartesian join and a not-exists to provide an
>> intermediate inline view that "fills in" the missing values. The final
>> result is then just a simple group-by+decode of that intermediate view.
>>
>> This just a simplified example of the real thing.
>>
>> select year
>> , sum( CASE WHEN category IN ('A1','A2')
>> THEN value1 ELSE NULL END ) AS sum_A
>> , sum( CASE WHEN category IN ('B1','B2')
>> THEN value1 ELSE NULL END ) AS sum_B
>> , sum( CASE WHEN category IN ('C' )
>> THEN value1 ELSE NULL END ) AS the_C
>> from (select year,category,value1 from big ugly join) my_intermediate_view
>> group by year
>>
>> I think I should be able to do the whole thing in the one select
>> statement - if I figure out how to correctly use the correct set of
>> analytic functions to provide the most recent values for the pairs of
>> values inside each sum.
>>
>> Can anyone provide insight on how to do this with analytic functions?
>>
>> Thanks for any feedback.
I don't think, this is an "uncomfotable" problem. It seems to me rather to be typical problem regarding data densification ( there are really good examples in data warehousing guide - http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14223/analysis.htm#sthref1840). My query may be influenced by "magic of input data" - in cases, if all categories are not available for certain year and still should be calculated for the same year, one need a join with row generator to create missing years, as you have shown ( in my query i silly ignore such possibility, as i'm not sure, such requirement exists, on top - i arrogantly stole the T1 table which you created ;-).
SQL> with t2 as(
2 select distinct 3 year, 4 last_value(decode(category,'A1',value1,null) ignore nulls) over(order by year) a1, 5 last_value(decode(category,'A2',value1,null) ignore nulls) over(order by year) a2, 6 last_value(decode(category,'B1',value1,null) ignore nulls) over(order by year) b1, 7 last_value(decode(category,'B2',value1,null) ignore nulls) over(order by year) b2, 8 last_value(decode(category,'C',value1,null) ignore nulls) over(order by year) c 9 from t1)
YEAR A1+A2 B1+B2 C ---------- ---------- ---------- ----------
2000 11 22 50
2001 13 24 50
2002 63 28 7
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 780 | 5 (40)|
00:00:01 |
| 1 | SORT ORDER BY | | 10 | 780 | 5 (40)|
00:00:01 |
| 2 | VIEW | | 10 | 780 | 5 (40)|
00:00:01 |
| 3 | HASH UNIQUE | | 10 | 290 | 5 (40)|
00:00:01 |
| 4 | WINDOW SORT | | 10 | 290 | 5 (40)|
00:00:01 |
| 5 | TABLE ACCESS FULL| T1 | 10 | 290 | 3 (0)|
00:00:01 |
Best regards
Maxim Received on Sat Mar 03 2007 - 14:05:59 CST
![]() |
![]() |