Reputation: 63
I'm trying to build a report that would essentially be a single query that combines the output of these queries:
select count(*) from my_table where createddate >= CURRENT_DATE - 1;
select count(*) from my_table where createddate >= CURRENT_DATE - 7;
select count(*) from my_table where createddate >= CURRENT_DATE - 30;
select count(*) from my_table where createddate >= CURRENT_DATE - 90;
select count(*) from my_table;
Such that the output would be similar to:
Time_Period Count
===================
Yesterday 5
Last Week 20
Last Month 50
Last 90 Days 100
Total 5000
I've had success building several linear time series queries (by day, by week, by month, etc). But no luck in being able to build a non-linear reporting query.
Upvotes: 1
Views: 48
Reputation: 65363
One option would be using Dynamic Query in PL/SQL along with defining arrays for day periods and their literal explanations :
SQL> set serveroutput on
SQL> declare
v_sql varchar2(250):='select count(*) from my_table where createddate >= current_date - :day';
v_prd owa.nc_arr;
v_str owa.vc_arr;
v_amount int;
begin
v_prd(1) := 1; v_prd(2) := 7; v_prd(3) := 30; v_prd(4) := 90; v_prd(5) := 100000;
v_str(1) := 'Yesterday'; v_str(2) := 'Last Week'; v_str(3) := 'Last Month';
v_str(4) := 'Last 90 Days'; v_str(5) := 'Total';
dbms_output.put_line('Time_Period Count');
dbms_output.put_line('===================');
for i in 1..5
loop
execute immediate v_sql into v_amount using v_prd(i);
dbms_output.put_line(rpad(v_str(i),14,' ')||v_amount);
end loop;
end;
/
where v_prd(5)
value could be as great as possible to contain all records of the table.
Upvotes: 0
Reputation: 222582
You can put the offsets in rows with union all
, then left join
them with your table, like:
select
o.time_period,
count(t.created) cnt
from (
select 'yesterday' time_period, 1 offs
union all select 'last week', 7
union all select 'last month', 30
union all select 'last 90 days', 90
union all select 'total', null
) o
left join mytable t on o.offs is null or t.created >= current_date - o.offs
group by o.time_period
Upvotes: 0
Reputation: 1270391
You can put the results in separate columns easily:
select sum(case when createddate >= CURRENT_DATE - 1 then 1 else 0 end) as yesterday,
sum(case when createddate >= CURRENT_DATE - 7 then 1 else 0 end) as last_week,
sum(case when createddate >= CURRENT_DATE - 30 then 1 else 0 end) as last_month,
sum(case when createddate >= CURRENT_DATE - 90 then 1 else 0 end) as last_90days,
count(*) as total
from my_table;
If you want separate rows, you can unpivot the above, or just use
union all
:
select 'Yesterday' as which, count(*) from my_table where createddate >= CURRENT_DATE - 1
union all
select 'Last week', count(*) from my_table where createddate >= CURRENT_DATE - 7
union all
select 'Last month', count(*) from my_table where createddate >= CURRENT_DATE - 30
union all
select 'Last 90 days', count(*) from my_table where createddate >= CURRENT_DATE - 90
union all
select 'Total', count(*) from my_table;
Upvotes: 1