最近6个月聚合

时间:2017-05-29 10:28:31

标签: oracle

我有包含调用数据的表,列CALLDATE包含调用的日期和时间。

我需要一个查询,它会返回过去6个月内每个月的来电次数。

结果如下:

PERIOD|CALLS
======|=====
201705|15235
201704|14965
201703|    0 <-- no data for this month
201702|12365
201701|13468
201612|14563

我有以下查询:

SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -1), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -0), 'MON')
UNION
SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -2), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -1), 'MON')
UNION
SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -3), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -2), 'MON')
UNION
SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -4), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -3), 'MON')
UNION
SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -5), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -4), 'MON')
UNION
SELECT COUNT (*)
  FROM mytable
 WHERE calldate BETWEEN TRUNC (ADD_MONTHS (SYSDATE, -6), 'MON')
                    AND TRUNC (ADD_MONTHS (SYSDATE, -5), 'MON')

也许有更简单的解决方案。

2 个答案:

答案 0 :(得分:0)

一种方法可能是创建一个月份列表,从sysdate开始到6个月前,并在外表jon方面使用你的表到这个表。 例如:

/* sample data */
with yourTable(callDate) as (
    select date '2017-05-15' from dual union all
    select date '2017-05-15' from dual union all
    select date '2017-04-15' from dual union all
    select date '2017-03-15' from dual union all
    select date '2017-03-15' from dual union all
    select date '2017-02-15' from dual union all
    select date '2016-12-15' from dual
)     
/* the query */
select count(callDate), 
       to_char(monthStart, 'yyyymm')
from (
        select add_months(trunc(sysdate, 'Month'), -level +1) monthStart,
               last_day(add_months(trunc(sysdate, 'Month'), -level +1)) monthEnd
        from dual
        connect by level <= 6
     ) months
     left join yourTable
       on calldate between monthStart and monthEnd
group by to_char(monthStart, 'yyyymm') 
order by to_char(monthStart, 'yyyymm') 

给出了:

COUNT(CALLDATE) TO_CHA
--------------- ------
              1 201612
              0 201701
              1 201702
              2 201703
              1 201704
              2 201705

6 rows selected.

这主要是基于一系列相关月份的开始和结束日的构建:

SQL> select add_months(trunc(sysdate, 'Month'), -level +1) monthStart,
  2                     last_day(add_months(trunc(sysdate, 'Month'), -level +1)) monthEnd
  3              from dual
  4              connect by level <= 6;

MONTHSTAR MONTHEND
--------- ---------
01-MAY-17 31-MAY-17
01-APR-17 30-APR-17
01-MAR-17 31-MAR-17
01-FEB-17 28-FEB-17
01-JAN-17 31-JAN-17
01-DEC-16 31-DEC-16

6 rows selected.

答案 1 :(得分:0)

你可以尝试这样的事情:

select TO_CHAR(CALLDATE,'yyyymm'),count(*)
from yourTable
--filter last n months (in this case 7)
where CALLDATE> SYSDATE - INTERVAL '7' MONTH
--group by month
group by TO_CHAR(CALLDATE,'yyyymm');

如果您在没有通话的情况下需要零个月:

WITH MONTH_COUNTER AS (
  SELECT LEVEL-1 AS ID 
  FROM DUAL 
  CONNECT BY LEVEL <= 6
), all_month as ( 
  --last 6 months
  SELECT TO_CHAR(ADD_MONTHS(sysdate, -ID),'yyyymm') m FROM MONTH_COUNTER
), all_count as (
  --previous query
  select TO_CHAR(CALLDATE,'yyyymm') m,count(*) c
  from yourTable
  where CALLDATE> SYSDATE - INTERVAL '7' MONTH
  group by TO_CHAR(CALLDATE,'yyyymm')
)
--nvl = when count(*) is null then put 0
select all_month.m,nvl(all_count.c,0)
from all_month
left outer join all_count
on all_month.m = all_count.m;