如何包含计数为0的月份名称以表示每月数据计数?

时间:2019-02-15 06:09:02

标签: sql sql-server sql-server-2012

我正在运行以下查询以获取去年到本月的去年的每月数据计数。

SELECT dateName(month,tn.processstarttime) as reqMonth, count(ID) as requestCount, year(tn.processstarttime) as reqYear
FROM table A tn WHERE  year(tn.processstarttime) in (year(DATEADD(MONTH, 0, GETDATE())),year(DATEADD(MONTH, -12, GETDATE()))) 
AND tn.processstarttime>DATEADD(MONTH, -12, GETDATE()) 
GROUP BY dateName(month,tn.processstarttime),year(tn.processstarttime)
order by dateName(month,tn.processstarttime),year(tn.processstarttime)

但是此查询未提供数据计数为0的月份名称。

请支持包括数据计数为0且值为0的月份。

谢谢

3 个答案:

答案 0 :(得分:2)

标准方法是使用所有年份和月份都必需的日历表,然后LEFT JOIN对其结果进行处理。如果您的表中没有对应的记录,那么您将使用COALESCE来获取这几个月的0。参见下面的查询(我使用CTE获取日历表,最简单的方法是IMO):

;with MonthNames as (
    select 1 MonthNo, 'January' MonthName
    union all
    select 2, 'February'
    union all
    select 3, 'March'
    union all
    select 4, 'April'
    union all
    select 5, 'May'
    union all
    select 6, 'June'
    union all
    select 7, 'July'
    union all
    select 8, 'August'
    union all
    select 9, 'September'
    union all
    select 10, 'October'
    union all
    select 11, 'November'
    union all
    select 12, 'December'
), Years as (
    select 2017 Year union all select 2018 union all select 2019
), CalendarTable as (
    select * from MonthNames cross join Years
)

select ct.MonthName,
       ct.Year,
       COALESCE(t.requestCount, 0) requestCount
from CalendarTable ct
left join (YOUR WHOLE SELECT) t
on t.Year = ct.Year and t.month = ct.MonthNo

答案 1 :(得分:1)

此答案可能与Michal Turczyn的答案相似,但有一些实质性差异:

不要太在意创建前两个CTE的差异,因为它们看上去无关紧要,只是样式问题。

重要的区别在于第三个CTE和过滤查询的方式,您的列名(processstarttime)提供了一个线索,它可以是一个非常大的表,因此,如果您在where子句中使用函数选定的表列,它将起作用,但是您的查询将不会被索引,并且性能可能会成为另一个问题

无关紧要,但也很重要的一点是,它涵盖了“去年到本月为止的去年的每月数据计数” PO的要求,而没有硬编码日期,它可以在视图或函数中,无需逐年修改...

WITH months AS (
        SELECT 1 AS MonthNum, DATENAME(Month,DATEFROMPARTS(1,1,1)) AS MonthName
        UNION ALL
        SELECT MonthNum + 1, DATENAME(Month,DATEFROMPARTS(1, MonthNum + 1, 1)) AS MonthName
        FROM months
        WHERE MonthNum <= 11
    ),
    years as (
        SELECT YEAR(GETDATE())-1 AS Year
        UNION ALL
        SELECT Year + 1
        FROM years 
        WHERE Year + 1 <= YEAR(GETDATE())
    ),
    dates as (
        SELECT Year, MonthNum, MonthName, DATEFROMPARTS(Year, MonthNum, 1) AS DateStart, DATEADD(MONTH, 1, DATEFROMPARTS(Year, MonthNum, 1)) AS DateEnd
        FROM years
        CROSS JOIN months
    )
    SELECT D.Year, D.MonthNum, D.MonthName, COUNT(ID) AS RequesCount
    FROM dates D
    LEFT JOIN  YourTable A ON A.ProcessStartTime >= DateStart AND A.ProcessStartTime < DateEnd
    WHERE DateStart < GETDATE()
    GROUP BY D.Year, D.MonthNum, D.MonthName
    ORDER BY Year, MonthNum

答案 2 :(得分:0)

尝试一下

SELECT months.month_name AS reqMonth, COUNT(ID) AS requestCount, YEAR(tn.processstarttime) AS reqYear
FROM A tn
    RIGHT JOIN (VALUES ('january'),('february'),('march'),('april'),
                       ('may'),('june'),('july'),('august'),('september'),
                       ('october'),('november'),('december')) as months(month_name) 
                ON DATENAME(month,tn.processstarttime) = months.month_name
                AND YEAR(tn.processstarttime) in (YEAR(DATEADD(MONTH, 0, GETDATE())),year(DATEADD(MONTH, -12, GETDATE()))) 
                AND tn.processstarttime>DATEADD(MONTH, -12, GETDATE()) 
GROUP BY months.month_name,YEAR(tn.processstarttime)
order by months.month_name,YEAR(tn.processstarttime)

实际here