【问题标题】:List all months with a total regardless of null列出所有月份的总数,而不考虑 null
【发布时间】:2017-12-14 14:28:53
【问题描述】:

我有一个非常小的 SQL 表,其中列出了参加的课程和参加日期。我可以使用下面的代码来统计每个月的参加人数

select to_char(DATE_ATTENDED,'YYYY/MM'),
COUNT (*)
FROM TRAINING_COURSE_ATTENDED
WHERE COURSE_ATTENDED = 'Fire Safety'
GROUP BY to_char(DATE_ATTENDED,'YYYY/MM')
ORDER BY to_char(DATE_ATTENDED,'YYYY/MM')

这会按预期返回每个月有与会者的列表。但是我想把它列为

January 2
February 0
March 5

如何将计数结果与空值一起显示?我的桌子很基础

1234    01-JAN-15   Fire Safety
108 01-JAN-15   Fire Safety
1443    02-DEC-15   Healthcare
1388    03-FEB-15   Emergency
1355    06-MAR-15   Fire Safety
1322    09-SEP-15   Fire Safety
1234    11-DEC-15   Fire Safety

我只需要显示每个月和参加消防安全的总人数。有一段时间没有使用 SQL 开发人员,因此感谢您的帮助。

【问题讨论】:

  • 您需要一个包含所有月份的表。我建议搜索“日历表”
  • ... right outer join calendar_table ...(我建议在左连接之前先右连接的极少数情况之一。)

标签: sql oracle count


【解决方案1】:

您需要一个日历表来选择要显示的时间段。简化后的代码如下所示:

select to_char(c.Date_dt,'YYYY/MM')
, COUNT (*)

FROM calendar as c
left join TRAINING_COURSE_ATTENDED as tca
 on tca.DATE_ATTENDED = c.Date_dt

WHERE tca.COURSE_ATTENDED = 'Fire Safety'
    and c.Date_dt between [period_start_dt] and [period_end_dt]
GROUP BY to_char(c.Date_dt,'YYYY/MM')
ORDER BY to_char(c.Date_dt,'YYYY/MM')

【讨论】:

    【解决方案2】:

    您可以使用 0 计数即时创建自己设置的所需年份月份,并使用如下查询。

    Select yrmth,sum(counter) from
    (
        select to_char(date_attended,'YYYYMM') yrmth,
               COUNT (1) counter
        From TRAINING_COURSE_ATTENDED Where COURSE_ATTENDED = 'Fire Safety'
        Group By Y to_char(date_attended,'YYYYMM')
        Union All
        Select To_Char(2015||Lpad(Rownum,2,0)),0 from Dual Connect By Rownum <= 12
    )
    group by yrmth
    order by 1
    

    如果要显示多个年份,只需将第二个查询更改为

    Select To_Char(Year||Lpad(Month,2,0)) , 0 
    From 
    (select Rownum Month from  Dual Connect By Rownum <= 12),
    (select 2015+Rownum-1 Year from  Dual Connect By Rownum <= 3)
    

    【讨论】:

      【解决方案3】:

      试试这个:

      SELECT Trunc(date_attended, 'MM') Month, 
             Sum(CASE 
                   WHEN course_attended = 'Fire Safety' THEN 1 
                   ELSE 0 
                 END) Fire_Safety 
      FROM   training_course_attended 
      GROUP  BY Trunc(date_attended, 'MM') 
      ORDER  BY Trunc(date_attended, 'MM') 
      

      【讨论】:

        【解决方案4】:

        另一种内联生成日历表的方法:

        with calendar (month_start, month_end) as
             ( select add_months(date '2014-12-01', rownum)
                    , add_months(date '2014-12-01', rownum +1) - interval '1' second
               from   dual
               connect by rownum <= 12 )
        select to_char(c.month_start,'YYYY/MM') as course_month
             , count(tca.course_attended) as attended
        from   calendar c
               left join training_course_attended tca
                    on   tca.date_attended between c.month_start and c.month_end
                    and  tca.course_attended = 'Fire Safety'
        group by to_char(c.month_start,'YYYY/MM')
        order by 1;
        

        (您也可以只在日历表中设置月份开始,并在trunc(tca.date_attended,'MONTH') = c.month_start 上加入,但如果您在tca.date_attended 上有索引或分区,效率可能会降低。)

        【讨论】:

          猜你喜欢
          • 2011-01-24
          • 2019-12-19
          • 2012-08-23
          • 2015-01-01
          • 1970-01-01
          • 2021-10-23
          • 1970-01-01
          • 1970-01-01
          • 2015-01-15
          相关资源
          最近更新 更多