Похоже, что это работает с примерами данных.
встроенные комментарии.
declare @table table (CoID int, PeriodType varchar(1), FinDate date, Sales int)
insert into @table
values (1, 'M' ,'9/30/18' ,11),
(1, 'M' ,'10/31/18',10),
(1, 'M' ,'11/30/18',10),
(1, 'M' ,'12/31/18',10),
(1, 'Q' ,'3/31/19' ,10),
(1, 'Q' ,'6/30/19' ,10),
(1, 'M' ,'7/31/19' ,10),
(1, 'M' ,'8/31/19' ,10),
(1, 'M' ,'9/30/19' ,10),
(2, 'M' ,'10/31/18',11),
(2, 'M' ,'11/30/18' ,12),
(2, 'M' ,'12/31/18' ,13),
(2, 'Q' ,'3/31/19' ,14),
(2, 'M' ,'4/30/19' ,15),
(2, 'M' ,'5/31/19' ,16),
(2, 'M' ,'6/30/19' ,17)
-- We need a table of months so we can determine if anything is missing.
declare @months table (mnth int)
insert into @months
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
-- This CTE takes the Quarter's sales and turns them into 3 months' sales
;with CTEquarterToMonth as (
-- start with the last month of a quarter
select CoID, month(FinDate) mnth, Sales
from @table t3
where findate >= eomonth(getdate(),-12)
and periodtype = 'Q'
union all
-- this is the 2nd month of the quarter, but only if it is also within 1 year
select CoID, month(dateadd("m",-1,FinDate)) mnth, 0 Sales
from @table t3
where findate >= eomonth(getdate(),-11)
and periodtype = 'Q'
union all
-- this is the 1st month of the quarter, but only if it is also within 1 year
select CoID, month(dateadd("m",-2,FinDate)) mnth, 0 Sales
from @table t3
where findate >= eomonth(getdate(),-10)
and periodtype = 'Q'
),
-- This CTE adds individual months to the months we already have gotten
-- from the Quarters' sales.
CTEcombinedMonths as (
select *
from CTEquarterToMonth
union all
select CoID, month(FinDate) mnth, Sales
from @table t
where findate >= eomonth(getdate(),-12)
and periodtype = 'M'
and not exists (select 1 -- This ignores duplicate months
from CTEquarterToMonth cte
where cte.CoID = t.CoID
and cte.mnth = month(FinDate)
)
)
select months.CoID,
-- The following case statement will set the sales to 0
-- if there are any missing months for a given CoID.
case when sum(case when cte.mnth is null then 1 else 0 end) > 0
then 0
else sum(Sales)
end YearSales
from ( -- derive a table of CoID's and all 12 months
select CoID, mnth
from @months
inner join (
select distinct CoID
from @table
) t on 1=1
) months
-- left join so we can find the missing months
left outer join CTEcombinedMonths cte
on months.CoID = cte.CoID
and months.mnth = cte.mnth
group by months.CoID
Вдохновленный частью ответа Мишель, мне нравится использовать count вместо таблицы @months. Вы можете полностью избавиться от таблицы @months и использовать следующий запрос после всех объявлений CTE:
select CoID,
-- The following case statement will set the sales to 0
-- if there are any missing months for a given CoID.
case when count(*) <> 12
then 0
else sum(Sales)
end YearSales
from CTEcombinedMonths cte
group by CoID