Skip to Main Content
  • Questions
  • Need a SQL query to pick Recent month data entered and it's previous month too.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, RS.

Asked: October 01, 2001 - 3:36 pm UTC

Last updated: February 17, 2003 - 11:15 am UTC

Version: 8.1.6

Viewed 1000+ times

You Asked

Hi Tom, I need little help in one SQL query.

I want to find-out SUM values for any choosen PRODUCT,for which 2 recent months it has got data(entered).

Consider a table, which has columns:
product-id Varchar2(10), ' MonthYear' Date, and 'ValueNbr' Number(20).

MonthYear column will have 'Full date' (dd-mon-yy hh24:mi:ss)entries.

For ex, product_cd " A " has got "value" entries till Jul2001.
When we query the table any month, ti should pick latest month it has got data and a month prior to that also.

the query should return :

Product_cd MonthYear Sum(ValueNbr)
---------- ------------ ---------------

A Jul2001 125
A Jun2001 235

( we can mention Product_cd in Where clause, Not a problem).
Your quick help is appreciated.

Awaiting your reply,


and Tom said...


ops$tkyte@ORA9I.WORLD> select object_type, to_char(created,'Mon YYYY') MonthYear, sum(object_id)
2 from all_objects
3 where created >= ( select trunc( add_months( max(created),-1 ), 'mm' )
4 from all_objects
5 where object_type = 'TABLE' )
6 and object_type = 'TABLE'
7 group by object_type, to_char(created,'Mon YYYY' )
8 /

OBJECT_TYPE MONTHYEA SUM(OBJECT_ID)
------------------ -------- --------------
TABLE Oct 2001 19981
TABLE Sep 2001 412913

Is one way to do it....

Rating

  (7 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Dear Tom

Nag, October 01, 2001 - 10:02 pm UTC

Is there anything you would say at least 'Ummmmmmm this is a difficult question , needs some thinking'

Are you a super human being, you have solutions and answers for each and every question.

what goes into making an expert like you , personality wise?

It is a personal question, but Iam forced to ask.

Yu are amazing.


Need a SQL query to pick Recent month data entered and it's previous month

Nathan, October 02, 2001 - 6:22 am UTC

Hi. Mr.Tom..
U r really Great.How can i Post my Questions to You...
pl give the details expecting your reply
Regards
Nathan

SQL query to pick Recent months data entered

Gonela, October 03, 2001 - 12:52 pm UTC

We appreicate your very quick and valuble reply , Thank you.
Though query works fine in SQL and returning exactly the same with our expectations.But we're experiencing problems in translating the same (query) to 'Business Objects' query.
The nested query mentioned in SQL, being translated to "HAVING clause" in BO, which is throwing out wrong result set.
Is there any possibility to acheive the same output in any other way? Response from BO forum is not quick unfrtunately.If time permits you, please suggest other possible ways to do. Otherwise, Thank you very much for your reply.

Tom Kyte
October 03, 2001 - 2:04 pm UTC

Can you create a view and hide the constructs from BO all together.

for example:

create view V
as
select object_type, to_char(created,'Mon YYYY') MonthYear, sum(object_id) sum_oid
from all_objects
where created >= ( select trunc( add_months( max(created),-1 ), 'mm' )
from all_objects
where object_type = userenv('client_info') )
and object_type = userenv('client_info')
group by object_type, to_char(created,'Mon YYYY' )
/

and then if BO permits the calling of PLSQL you would:

begin dbms_application_info.set_client_info( 'TABLE' ); end;

and just select * from V;

(i call this a "parameterized view")


does that get around this BO limitation?

Extremely use for DSS system application

Bhagat Singh, October 03, 2001 - 11:53 pm UTC

Hello Tom,

Can we transpose the same result in this way

OBJECT_TYPE OCT SEP Total
----------------------------------------------
TABLE 10 30 40


Please help regarding this.


Regards
Bhagat Singh

Tom Kyte
October 04, 2001 - 6:39 am UTC

well, we cannot do the column headings like that unless you want to do dynamic sql (then I can write a procedure that returns this result set exactly).

In straight sql, one approach is:

ops$tkyte@ORA817DEV.US.ORACLE.COM> select object_type,
  2         max( decode( rn, 1, sum_oid, null ) ) month1,
  3         max( decode( rn, 2, sum_oid, null ) ) month2,
  4         max( decode( rn, 1, sum_oid, null ) ) +
  5         max( decode( rn, 2, sum_oid, null ) ) summed,
  6         min( monthYear ),
  7         max( monthYear )
  8  from (
  9  select object_type,
 10         monthYear,
 11         row_number() over ( partition by object_type
 12                             order by monthYear ) rn,
 13         sum_oid
 14    from (
 15  select object_type, trunc(created,'mm') MonthYear, sum(object_id) sum_oid
 16    from all_objects
 17   where created >= ( select trunc( add_months( max(created),-1 ), 'mm' )
 18                                            from all_objects
 19                                           where object_type = 'TABLE' )
 20     and object_type = 'TABLE'
 21   group by object_type, trunc(created,'mm')
 22     )
 23  )
 24  group by object_type
 25  /

OBJECT_TYPE            MONTH1     MONTH2     SUMMED MIN(MONTH MAX(MONTH
------------------ ---------- ---------- ---------- --------- ---------
TABLE                  225648      57131     282779 01-SEP-01 01-OCT-01


 

AVG_ROW_LEN

Abhitha Kuj, October 04, 2001 - 10:42 pm UTC

sQL> create table temp(tdate date);

Table created.

SQL> analyze table temp compute statistics;

Table analyzed.

SQL> select avg_row_len from all_tables where table_name='TEMP';

AVG_ROW_LEN
0                                                                                         

SQL> insert into temp values(sysdate);

1 row created.

SQL>  analyze table temp compute statistics;

Table analyzed.

SQL> select avg_row_len from all_tables where table_name='TEMP';

AVG_ROW_LEN
11                                                                                         

SQL> insert into temp values(null);

1 row created.

SQL>  analyze table temp compute statistics;

Table analyzed.

SQL> select avg_row_len from all_tables where table_name='TEMP';

AVG_ROW_LEN
7                                                                                         

SQL> delete temp where tdate is null;

1 row deleted.

SQL> commit;

Commit complete.

SQL>  analyze table temp compute statistics;

Table analyzed.

SQL> select avg_row_len from all_tables where table_name='TEMP';

AVG_ROW_LEN
11

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Our Business billing requirement (B2B) calls for data storage consumption per month by the Clients and partners. We normally use AVG_ROW_LEN to calculate the data storage consumption ... By this you would have understood what is our problem by going through above sql spool file. Is AVG_ROW_LEN reliable for such type of storage consumption calculations?? Pls Help. 

Tom Kyte
October 05, 2001 - 11:44 am UTC

NOT that this question in the followup section here has ANYTHING WHATSOEVER to do with the question at hand (what possible link is there between avg_row_len and need a sql query to pick recent month data...??? I couldn't find any.)

No, I don't understand your issue. What is it exactly? If the issue is "why does 1 row with a date have an avg_row_len of 11", thats called overhead. If the issue is why do two rows, one null and the over not null, have an avg_row_len of 7 -- the answer is 11 bytes for one row, 3 or 4 bytes for the other -- thats 14/15 which has an average of 7.

Looks all very normal to me.

Need a SQL query to pick Recent month data entered and it's previous month too.",

Ram, October 04, 2001 - 11:09 pm UTC

Hi Mr.Tom,
Is this calculation includes new table creation ?..Pl let me know

Tom Kyte
October 05, 2001 - 11:51 am UTC

no idea what you mean there.

What if there are mutiple rows

A reader, February 17, 2003 - 4:09 am UTC

Hi,
What query can you use if we need to join the tables, and display data of multiple months,
My requirement is a litle different, i need to display mutiple rows and the previous month data as zero even if there were no records.
There may be many types i.e object types and many months of data. I cannot restrict that.
To sum it up for a Row it should display the previous months data.if there is no data found for previos month then display Zero,
If there is data just for the Previous month then display current months data as zero and previous months actual data.

The result set would look something like whats there below

Object_type Month Amount PrevMonthAmount
----------------------------------------------------
Table Jan2003 1000 0
Procedure JAN2003 2000 10000
Table Feb2003 20020 10000
Procedure Feb2003 0 1000




I need to have this in a single query, i can create views or MV or anything like that, but a single query cant have a procedure is it possible






Tom Kyte
February 17, 2003 - 11:15 am UTC

well, your output is a little funky.  

for example, why is there a procedure with amount = 0 but no table with amount = 0?

why is there a table with a prevmonthamount = 0, yet no procedure with the same?  

I mean -- according to your rules, there would be both for both?


But in any case -- here is one that shows the amounts by month and if there is a prior months amount -- that is included, else it is zero:

ops$tkyte@ORA920> select object_type, month, amount,
  2         decode( add_months(month,-1), last_month, last_amt, 0 ) last_month
  3    from (
  4  select object_type, month, amount,
  5         lag(amount) over (partition by object_type order by month ) last_amt,
  6         lag(month) over (partition by object_type order by month ) last_month
  7    from (
  8  select object_type, month, sum(amount) amount
  9    from t
 10   group by object_type, month
 11         )
 12         )
 13  /

OBJECT_TYPE        MONTH         AMOUNT LAST_MONTH
------------------ --------- ---------- ----------
PROCEDURE          01-MAY-02     505564          0
PROCEDURE          01-SEP-02      31158          0
PROCEDURE          01-OCT-02      31886      31158
PROCEDURE          01-DEC-02      34561          0
PROCEDURE          01-JAN-03     221431      34561
TABLE              01-MAY-02   11727977          0
TABLE              01-AUG-02     182975          0
TABLE              01-OCT-02      32177          0
TABLE              01-NOV-02      34031      32177
TABLE              01-DEC-02     104999      34031
TABLE              01-JAN-03    2377920     104999
TABLE              01-FEB-03   38537263    2377920

12 rows selected.

Now, if you REALLY need those extra rows (not clear) with amount=0 and prevmonthamounts -- then we can cartesian product with a 2 row table (we need to output that last row for each object type twice see) and do a little decodeing:

ops$tkyte@ORA920> select object_type,
  2         decode( xx, 1, month, add_months(month,1)) month,
  3             decode( xx, 1, amount, 0 ) amount,
  4             decode( xx, 1, last_month, amount) last_month,
  5             xx
  6    from (
  7  select object_type, month, amount,
  8         decode( add_months(month,-1), last_month, last_amt, 0 ) last_month,
  9             max(month) over ( partition by object_type ) max_month,
 10             xx
 11    from (
 12  select object_type, month, amount,
 13         lag(amount) over (partition by object_type order by month ) last_amt,
 14         lag(month) over (partition by object_type order by month ) last_month
 15    from (
 16  select object_type, month, sum(amount) amount
 17    from t
 18   group by object_type, month
 19         )
 20         ), (select 1 xx from dual union all select 2 xx from dual )
 21         )
 22   where xx = 1 OR ( xx = 2 and month = max_month )
 23   order by 1,2
 24  /

OBJECT_TYPE        MONTH         AMOUNT LAST_MONTH         XX
------------------ --------- ---------- ---------- ----------
PROCEDURE          01-MAY-02     505564          0          1
PROCEDURE          01-SEP-02      31158          0          1
PROCEDURE          01-OCT-02      31886      31158          1
PROCEDURE          01-DEC-02      34561          0          1
PROCEDURE          01-JAN-03     221431      34561          1
PROCEDURE          01-FEB-03          0     221431          2
TABLE              01-MAY-02   11727977          0          1
TABLE              01-AUG-02     182975          0          1
TABLE              01-OCT-02      32177          0          1
TABLE              01-NOV-02      34031      32177          1
TABLE              01-DEC-02     104999      34031          1
TABLE              01-JAN-03    2377920     104999          1
TABLE              01-FEB-03   38537263    2377920          1
TABLE              01-MAR-03          0   38537263          2

14 rows selected.



there you are.