当几个月有空数据时,如何在使用Datepart时包括所有月份?

时间:2013-12-27 20:02:47

标签: sql sql-server sql-server-2008

当几个月有空数据时,如何包含使用Datepart的所有月份?

我有去年的销售和退款数据,但有些月份有NULL数据。如何包含这些月份,并有ROW_NUMBER增量?

SELECT
    ROW_NUMBER() OVER (ORDER BY DATEPART(Year, SalesDate), DATEPART(MONTH, SalesDate)) AS 'RowNumber',  
    LEFT(datename(MONTH, SalesDate),3) AS 'Month',
    DATEPART(Year, SalesDate) AS 'Year',
    SUM(Refunds) 'Refunds',
    COUNT(Sales),
    SUM(Refunds) / COUNT(Sales) AS 'Percent Refunds'

FROM Sales_Table
WHERE SalesDate BETWEEN '10/01/2012' AND '12/31/2013'

GROUP BY DATEPART(Year, SalesDate), DATEPART(Month, SalesDate), DATENAME(month, SalesDate)

输出如下:

enter image description here

但是你可以看到2012年12月缺失了。我已经尝试过使用ISNULL和CASE WHEN NULL对计数和总和无效。

提前致谢!

3 个答案:

答案 0 :(得分:0)

Kluge但快速修复

创建一个变量表@tblMonthYear,其中包含每个月组合的记录(代码省略)

所以@tblMonthYear有这三个字段

2000年1月1日

2000年2月2日

2020年12月12日

    SELECT
        ROW_NUMBER() OVER (ORDER BY DATEPART(Year, SalesDate), 
                           DATEPART(MONTH, SalesDate)) AS 'RowNumber',  
        LEFT(datename(MONTH, SalesDate),3) AS 'Month',
        DATEPART(Year, SalesDate) AS 'Year',
        SUM(Refunds) 'Refunds',
        COUNT(Sales),
        SUM(Refunds) / COUNT(Sales) AS 'Percent Refunds'

FROM Sales_Table
LEFT JOIN @tblMonthYear
on @tblMonthYear.Month =LEFT(datename(MONTH, SalesDate),3)
and @tblMonthYear.Year = DATEPART(Year, SalesDate) AS 'Year'

WHERE SalesDate BETWEEN '10/01/2012' AND '12/31/2013'

答案 1 :(得分:0)

创建tmp表,如下所示:

create table #tmpTable (SalesDate dateTime,Refunds int,Sales int)
-- Populate
INSERT INTO #tmpTable VALUES ( '1/1/2013',0,0 )
INSERT INTO #tmpTable VALUES ( '2/1/2013',0,0 )
INSERT INTO #tmpTable VALUES ( '3/1/2013',0,0 )
INSERT INTO #tmpTable VALUES ( '4/1/2013',0,0 )

现在,调整你的代码

   FROM ( select sales_date,sales,refunds from Sales_Table
          union
          select * from #tmpTable  xx
          left join Sales_table st on month(xx.sales_date)=month(st.sales_date) and 
                                      year(xx.sales_date)=year(st.sales_Date) 
          WHERE st.sales_date is null
        ) Sales_table
      WHERE SalesDate BETWEEN '10/01/2012' AND '12/31/2013'

没有样本数据并且即时输入,但应该开始

答案 2 :(得分:0)

这是我为测试而生成的随机数据....

create table Sales_Table (
    SalesDate date,
    Sales decimal(18,2),
    Refunds decimal(18,2))

insert into Sales_Table (SalesDate, Sales, Refunds)
values ('2013-01-15',1.99,0),
('2013-02-15',2.99,0),
('2013-03-15',3.99,0),
('2013-04-15',4.99,0),
('2013-05-15',5.99,0),
('2013-06-15',6.99,15),
('2013-07-15',7.99,0),
('2013-08-15',8.99,0),
('2013-09-15',8.99,0),
('2013-10-15',8.99,0),
('2013-11-15',8.99,0)

我添加了日历表...还使用了年份和月份函数而不是datepart(我发现它更具可读性)。

; WITH Calendar AS (
    select m.number as [month], y.number as [year], 
        left(datename(month,convert(varchar,y.number)+'-'+convert(varchar,m.number)+'-'+'01'),3) as [monthname]
    from master..spt_values y
    cross join master..spt_values m
    where y.type = 'p' and y.number between 2012 and 2013 
      and m.type = 'p' and m.number between 1 and 12
      and y.number*100 + m.number between 201210 and 201312
), SalesData AS (
    SELECT
        Year(SalesDate) AS 'Year',
        Month(SalesDate) AS 'Month',
        SUM(Refunds) AS 'Refunds',
        COUNT(Sales) AS 'SalesCount',
        SUM(Refunds) / COUNT(Sales) AS 'Percent Refunds'
    FROM Sales_Table
    WHERE SalesDate BETWEEN '10/01/2012' AND '12/31/2013'
    GROUP BY DATEPART(Year, SalesDate), DATEPART(Month, SalesDate), DATENAME(month, SalesDate)
)
select row_number() over (order by c.[year],c.[month]) as 'RowNumber',
    c.[monthname] as 'Month',
    c.[year] as 'Year',
    coalesce(sd.Refunds,0) as 'Refunds',
    coalesce(sd.SalesCount,0) as 'SalesCount',
    coalesce(sd.[Percent Refunds],0) as 'Percent Refunds'
from Calendar c
left join SalesData sd
  on c.[year] = sd.[year]
  and c.[month] = sd.[month]
order by c.[year],c.[month]