1

希望获得每个月的记录数。但是,几个月没有记录,因此不返回任何行。我怎样才能得到那个月的 0 计数?

select months, count(rowid) as counter from (
    select  to_char(date_entered, 'MM') as months
    from mydatatable
    where to_char(date_entered, 'yyyy') = '2011'
     )
group by months
order by months

结果:

Month    Count
01       32
03       12
04       11
06       10
07       222
08       32

甚至尝试使用 subqselect 1,2,3,4,5,6,7,8,9,10,11,12 from dual并无法使其正常工作。还没有枢轴功能... ;(

4

4 回答 4

2

您最好将 01 到 12 存储在表中,但一般方法是使用左连接:

Select
  m.Mo,
  Count(t.dateentered)
From (
    Select '01' As Mo From Dual Union All
    Select '02' From Dual Union All
    Select '03' From Dual Union All
    Select '04' From Dual Union All
    Select '05' From Dual Union All
    Select '06' From Dual Union All
    Select '07' From Dual Union All
    Select '08' From Dual Union All
    Select '09' From Dual Union All
    Select '10' From Dual Union All
    Select '11' From Dual Union All
    Select '12' From Dual
  ) m
    Left Outer Join
  mydatatable t
    On
      m.Mo = to_char(t.dateentered, 'MM') And 
      t.dateentered >= DATE'2011-01-01' And
      t.dateentered < DATE'2012-01-01'
Group By
  m.Mo
Order By
  m.Mo

更新使用了一种对索引更友好的方式来限制年份。

http://sqlfiddle.com/#!4/68085/10

于 2013-01-18T17:52:43.223 回答
1

您需要构建自己的 12 行月“表”并执行左外连接。从您的问题中获取查询并使其成为提供数据的内联视图。

SELECT m.month "Month", nvl(md.data, 0) "Count"
FROM
(
   select '01' month from dual union all
   select '02' month from dual union all
   select '03' month from dual union all
   select '04' month from dual union all
   select '05' month from dual union all
   select '06' month from dual union all
   select '07' month from dual union all
   select '08' month from dual union all
   select '09' month from dual union all
   select '10' month from dual union all
   select '11' month from dual union all
   select '12' month from dual
) m LEFT OUTER JOIN (
   /* Your Query Here */
) md ON m.month = md.month
ORDER BY m.month;

结果应该是这样的:

Month       Count
------ ----------
01             32
02              0
03             12
04             11
05              0
06             10
07            222
08             32
09              0
10              0
11              0
12              0
于 2013-01-18T17:41:07.427 回答
0

connect by您可以使用分层查询的语法构建一个包含月份数字的虚拟表,然后左连接到您的数据:

with months as (
    select to_char(level, 'FM00') as month
    from dual
    connect by level <= 12
)
select m.month,
    count(mdt.rowid) as counter
from months m
left join mydatatable mdt
    on mdt.date_entered >= to_date('01/' || m.month || '/2011', 'DD/MM/YYYY')
    and mdt.date_entered <
        add_months(to_date('01/' || m.month || '/2011', 'DD/MM/YYYY'), 1)
group by m.month
order by m.month;

使用一些虚构的数据:

create table mydatatable (date_entered date, dummy number);
insert into mydatatable values (date '2011-06-02', 0);
insert into mydatatable values (date '2011-07-01', 0);
insert into mydatatable values (date '2011-10-01', 0);
insert into mydatatable values (date '2011-10-31', 0);
insert into mydatatable values (date '2011-11-01', 0);

...这给出了:

MONTH COUNTER
----- -------
01          0 
02          0 
03          0 
04          0 
05          0 
06          1 
07          1 
08          0 
09          0 
10          2 
11          1 
12          0 

或者SQL Fiddle,因为这似乎是这些天要做的事情......


通常最好避免这样的事情,to_char(date_entered, 'yyyy') = '2011'因为您将该to_char()函数应用于表中的每一行,并且如果该列上有索引,则不会使用它。而是尝试转换您的过滤器以匹配列的数据类型,例如date_entered > date '2011-01-01' and date_entered < date '2012-01-01'. 在这种情况下,无论如何都可以在连接条件中处理它 - 我将每个月转换为 2011 年的日期范围,并且只查找该月份范围内的匹配记录。

于 2013-01-18T17:45:15.653 回答
0

这很奇怪......也许我误解了问题或数据......?在您的问题中添加表格和数据总是一个好主意。您应该使用 count 获取所有月份的所有数据。我试过这个:

SELECT * FROM stack_test
/
CURR_MONTH  VAL
---------------
01          10
02          15
03          20
04  
05  

如您所见,第 4 个月和第 5 个月没有值:

 SELECT months, COUNT(rowid) counter 
   FROM
    (
     SELECT curr_month months
       FROM stack_test
    )
 GROUP BY months
 ORDER BY months
 /
 MONTHS COUNTER
 -------------------
 01           1
 02           1
 03           1
 04           1
 05           1

另一个例子:第 2 个月没有任何价值,但我当然仍然得到计数。也许你需要总结你的价值观......:

SELECT mth, SUM(val) total_sum, Count(*) total_cnt 
  FROM 
  (
  SELECT mth, (CASE WHEN Mth = '01' THEN '10' ELSE '0' END) val
    FROM
    ( -- Annual table - replace 2 with 12 in Add_Months for the whole year -- 
     SELECT Trunc(SYSDATE,'Y')+Level-1 Curr_Year_By_Date
        , To_char(Trunc(SYSDATE, 'MM') + Rownum-1, 'MM' ) Mth
     FROM dual
    CONNECT BY Level <= Add_Months(Trunc(SYSDATE,'Y'),2)-Trunc(SYSDATE,'Y')
   )
  )
 GROUP BY mth
 ORDER BY 1
 /
 MTH    TOTAL_SUM   TOTAL_CNT
 -------------------------------------
 01         310         31
 02         0           28
于 2013-01-18T19:21:59.050 回答