Oracle DB - 单次查询非线性时间分组报表(1天,1周,1个月,3个月,总计)

Oracle DB - Single query non-linear time grouping report (1 day, 1 week, 1 month, 3 months, total)

我正在尝试构建一个报告,该报告本质上是一个结合了这些查询输出的查询:

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;

这样输出类似于:

Time_Period   Count
===================
Yesterday        5
Last Week       20
Last Month      50
Last 90 Days   100
Total         5000

我已成功构建多个线性时间序列查询(按天、按周、按月等)。但是没有运气能够构建非线性报告查询。

您可以轻松地将结果放在单独的列中:

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;

如果你想要单独的行,你可以取消透视上面的内容,或者只使用 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;

您可以使用 union all 将偏移量放在行中,然后 left join 使用您的 table,例如:

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

一个选项是在 PL/SQL 中使用动态查询以及为日期段定义数组及其字面解释:

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;  
/

其中 v_prd(5) 值可以尽可能大以包含 table.

的所有记录