如何填写缺失月份的数据超过1年

时间:2017-01-18 08:21:32

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

我有一份报告,显示从项目开始到当前月份的一系列项目的月度数据。当项目几个月没有数据时,它就不会显示出来。

我需要为每个项目显示缺少的月份行,并为这些行显示0。

可以有2个或更多项目(如100个项目)生成报告。项目开始时间也可以是2014年的早期项目。 假设当前月份是2016年4月。然后报告需要显示从201401到201604的数据。在下面的示例中,我使用项目开始月份作为201512。

所有月份列表都存储在包含所有月份的月份表中。项目开始月份(201512和当前月份201604作为参数传递给storedprocedure)

目前报告看起来像这样

=====================================
|ProjectNo | Period | Billing | WIP  |
======================================
|000123    |201512  | 100      | 75  |  
|          |201601  | 200      | 100 | 
--------------------------------------
|000145    |201512  | 100      | 75  |
|          |201601  | 200      | 100 |
|          |201602  | 250      | 110 |    
|          |201604  | 550      | 110 |
======================================

返回的数据集如下所示(让结果集调用为ProjectReportData)

=====================================
|ProjectNo | Period | Billing | WIP  |
======================================
|000123    |201512  | 100      | 75  |  
|000123    |201601  | 200      | 100 | 
|000145    |201512  | 100      | 75  |
|000145    |201601  | 200      | 100 |
|000145    |201602  | 250      | 110 |    
|000145    |201604  | 550      | 110 |
======================================

如您所见,项目编号000123缺少201602,201603和201604。 对于项目号000145,缺少201603个月。

预期输出就像这样

=====================================
|ProjectNo | Period | Billing | WIP  |
======================================
|000123    |201512  | 100      | 75  |  
|          |201601  | 200      | 100 |
|          |201602  | 0        | 0   |
|          |201603  | 0        | 0   |
|          |201604  | 250      | 110 |  
--------------------------------------
|000145    |201512  | 100      | 75  |
|          |201601  | 200      | 100 |
|          |201602  | 250      | 110 | 
|          |201603  | 0        | 0   |   
|          |201604  | 550      | 110 |
======================================

我尝试使用Months表右键加入ProjectReportData, 这将填补失踪的几个月。

|ProjectNo | Period | Billing | WIP  |
======================================
|000123    |201512  | 100      | 75  | 
|000123    |201601  | 200      | 100 | 
|NULL      |201602  | NULL     | NULL|
|NULL      |201603  | NULL     | NULL| 
|NULL      |201604  | NULL     | NULL|  
|000145    |201512  | 100      | 75  |
|000145    |201601  | 200      | 100 |
|000145    |201602  | 250      | 110 | 
|NULL      |201603  | NULL     | NULL|    
|000145    |201604  | 550      | 110 |
======================================

但我还需要填充ProjectNo而不是NULL。

我怎样才能实现这一目标。请建议。

2 个答案:

答案 0 :(得分:0)

在CTE中加入交叉联接:

with Projects as
(
select distinct ProjectNumber
from ProjectReportData 
)
, Periods as
(
select p.ProjectNumber, c.Period
from Projects p
cross join CalendarTable c
)
select a.*, b.Billing, b.WIP
from Periods a
left join ProjectReportData b
  on a.ProjectNumber = b.ProjectNumber 

答案 1 :(得分:0)

如果数据库中有Projects表:

select ProjectNo, Period, IsNull(wip, 0) wip , IsNull(billing, 0) billing
from Projects d1
outer apply (
    select m.*,d2.wip, d2.billing
    from Months m
    left join ProjectReportData d2 on m.Period = d2.Period and d2.ProjectNo=d1.ProjectNo
) mm
order by 1, 2 desc

如果您的数据库中没有Projects表:

select ProjectNo, Period, IsNull(wip, 0) wip , IsNull(billing, 0) billing
from (
    select distinct ProjectNo
    from ProjectReportData 
) d1
outer apply (
    select m.*,d2.wip, d2.billing
    from Months m
    left join ProjectReportData d2 on m.Period = d2.Period and d2.ProjectNo=d1.ProjectNo
) mm
order by 1, 2 desc