如何在数月内不在数据库中返回零

时间:2014-09-09 03:21:49

标签: sql oracle date-arithmetic

我正在尝试返回在特定月份注册的人数,但是也希望在数据库中没有的月份内返回零。

以下查询返回数据库中以月份注册的人数:

select 
    extract(year from "DATECREATED") as YEAR, 
    extract(month from "DATECREATED") as mon,
    count("USERID") as Total
from 
    TBLG2O_USEROFO 
where 
    extract(year from "DATECREATED") = '2014'
group by 
    extract(year from "DATECREATED"), 
    extract(month from "DATECREATED")
order by 
    1, 2

3 个答案:

答案 0 :(得分:1)

我在mysql上测试了这个,所以你可能需要对oracle进行一些修改。

首先创建一个包含一年中几个月的表格...

create table months(month int);
insert into months values(1);
insert into months values(2);
insert into months values(3);
insert into months values(4);
insert into months values(5);
insert into months values(6);
insert into months values(7);
insert into months values(8);
insert into months values(9);
insert into months values(10);
insert into months values(11);
insert into months values(12);

使用与Month表的右连接来达到预期的效果:

select coalesce(YEAR, 2014) year, m.month, coalesce(Total, 0) as total 
from 
  (select year(DATECREATED) as YEAR, month(c. DATECREATED) month, count("DATECREATED") as Total 
  from comments c
  where year(DATECREATED) ='2014'
  group by year, month(c.date_sent)) as c
right join months m
on c.month = m.month
order by year, month

如果您无法添加临时表,可以尝试以下方法:

select coalesce(YEAR, 2014) year, m.month, coalesce(Total, 0) as total 
from 
  (select year(DATECREATED) as YEAR, month(c. DATECREATED) month, count("DATECREATED") as Total 
  from comments c
  where year(DATECREATED) ='2014'
  group by year, month(c.date_sent)) as c
right join
  (select 1 as month union select 2 as month union select 3 as month 
   union select 4  as month union select 5 as month union select 6 as month 
   union select 7 as month union select 8 as month union select 9 as month 
   union select 10 as month union select 11 as month union select 12 as month) m
on c.month = m.month
order by year, month

答案 1 :(得分:0)

不幸的是,要做到这一点,你需要一个只包含每行月份数的第二个表。

假设您创建了一个名为MONTHS的表,其中包含一列MONTH_NUMBER,您可以使用此查询创建您要查找的输出 - 它将计算每行的行数您指定的年份的月份,并且在没有行的任何月份显示零。

请注意,此查询也有一个缺点 - 它只能在一个日历年内工作,因此您无法在多年内(例如,2013年7月 - 2014年6月)将其拆分。

SELECT COALESCE(YEAR, 2014) AS YEAR,
       MONTHS.MONTH_NUMBER  AS MONTH,
       COALESCE(TOTAL, 0)   AS "MONTH COUNT"
  FROM (SELECT EXTRACT(YEAR FROM DATECREATED) AS YEAR,
               EXTRACT(MONTH FROM DATECREATED) AS MONTH,
               COUNT(DATECREATED) AS TOTAL
          FROM TBLG2O_USEROFO            
         WHERE EXTRACT(YEAR FROM DATECREATED) = '2014'
         GROUP BY EXTRACT(YEAR FROM DATECREATED), 
                  EXTRACT(MONTH FROM DATECREATED)) LFT
      RIGHT OUTER JOIN MONTHS
               ON MONTH_NUMBER = LFT.MONTH
 ORDER BY YEAR, MONTH

See this query in action at SQL Fiddle

基本上,这是@Eran's MySQL answer的Oracle版本。

答案 2 :(得分:0)

在Oracle中,当您需要“合成”不直接存在于数据库中的行时,可以使用建模子句model keyword

我使用Jared的SQL Fiddle生成更简单的示例,没有任何第二个表:

select * from
(
  select count(1) cnt, trunc(datecreated, 'MONTH') dt
  from TBLG2O_USEROFO
  group by trunc(datecreated, 'MONTH')
)
model
--partition by (department)
dimension by (dt)
measures (cnt, cast (null as number) tech_cnt)
rules sequential order(
    tech_cnt[ for dt from to_date('2013-01-01','RRRR-MM-DD') 
                       to to_date('2014-12-31','RRRR-MM-DD') 
                increment NUMTOYMINTERVAL(1,'MONTH')] 
    = nvl(cnt[cv(dt)], 0)
)
order by dt;

想象一下查询的结果是Excel工作表。然后,作业tech_cnt[dt] = nvl(cnt[cv(dt), 0)是一个“excel宏”。