2013-01-18 203 views
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 

即使試圖用SUBQ select 1,2,3,4,5,6,7,8,9,10,11,12 from dual打,不能得到它的工作。 (

回答

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

+0

還沒有聽說過sqlfiddle,但始終使用jsfiddle。這只是讓我的一天感謝。 – Zippy

+0

除非優化器已經發展到這樣做,否則可以通過在加入之前聚合來自mydatatable的每月數字來削減一小部分工作。 –

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 
0

您可以建立一個使用connect by syntax of a hierarchical query包含月份數字的虛表,然後左鍵加入到你的數據:

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年的日期範圍,並且只查找該月份範圍內的匹配記錄。

+0

感謝您使用to_char的提示,sql很好。我需要繼續學習,因爲我需要一些星期五來彌補我的知識。通常我不會深入研究數據庫內容。 – Zippy

0

這是很奇怪的......也許我誤解了問題或資料...?向你的問題添加表格和數據總是個好主意。你應該得到所有月份的所有數據。我嘗試這樣做:

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