Ustawiłbym twoje zapytanie nieco inaczej, ponieważ chociaż jest ono dynamiczne, ponieważ zmieniają się nazwy kolumn, nadal masz zakodowaną liczbę kolumn.
Najpierw użyłbym rekurencyjnego CTE do wygenerowania listy miesięcy/lat, które chcesz utworzyć.
DECLARE @startDate datetime
SET @startDate = '2013-01-01'
;with dates as
(
select @startdate datelist, 1 sp
union all
select dateadd(month, 1, datelist), sp+1
from dates
where sp+1 <= 5 -- change this number 5 to the number of months you need
)
select sp,
REPLACE(SUBSTRING(CONVERT(varchar(11), datelist, 13), 4, 8), ' ', '') MONTHANDYEAR
from dates
Zobacz SQL Fiddle z wersją demonstracyjną . Spowoduje to automatyczne utworzenie listy 5 miesięcy z rokiem. Wtedy nie kodujesz na stałe 5 kolumn. Twoje aktualne zapytanie nie jest tak elastyczne, jak mogłoby być. Co się stanie, jeśli będziesz chciał 12 miesięcy, będziesz musiał zmienić swój kod.
Po wygenerowaniu listy dat wstawiłbym ją do tabeli tymczasowej, abyś mógł jej użyć do pobrania kolumn.
Kod do pobrania listy kolumn to:
select @cols = STUFF((SELECT ',' + QUOTENAME(monthandyear)
from #datesTemp
group by monthandyear, sp
order by sp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colNames = STUFF((SELECT ', isnull(' + QUOTENAME(monthandyear)+', 0) as '+QUOTENAME(monthandyear)
from #datesTemp
group by monthandyear, sp
order by sp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Zobacz SQL Fiddle z wersją demonstracyjną
. Zobaczysz, że istnieją dwie wersje. Pierwszy @cols
pobiera listę kolumn, które będą używane w pivot
. Drugi @colNames
zostanie użyty w końcowym SELECT
lista do zastąpienia null
wartości z zerami.
Następnie składasz wszystko razem, a kod będzie wyglądał następująco:(Uwaga:używam wersji mojej odpowiedzi z Twojego poprzednie pytanie )
DECLARE @cols AS NVARCHAR(MAX),
@colNames AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@startDate datetime
SET @startDate = '2013-01-01'
;with dates as
(
select @startdate datelist, 1 sp
union all
select dateadd(month, 1, datelist), sp+1
from dates
where sp+1 <= 5 -- change this number 5 to the number of months you need
)
select sp,
REPLACE(SUBSTRING(CONVERT(varchar(11), datelist, 13), 4, 8), ' ', '') MONTHANDYEAR
into #datesTemp
from dates
select @cols = STUFF((SELECT ',' + QUOTENAME(monthandyear)
from #datesTemp
group by monthandyear, sp
order by sp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colNames = STUFF((SELECT ', isnull(' + QUOTENAME(monthandyear)+', 0) as '+QUOTENAME(monthandyear)
from #datesTemp
group by monthandyear, sp
order by sp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT resource, clientname,' + @colNames + '
from
(
select [CLIENTNAME], [RESOURCE], [FORECASTTOTAL],
REPLACE(SUBSTRING(CONVERT(varchar(11), SCHEDULEDDATE, 13), 4, 8), '' '', '''') monthandyear
from viewprojscheduling_group
) x
pivot
(
sum(FORECASTTOTAL)
for monthandyear in (' + @cols + ')
) p '
execute(@query)
Zobacz SQL Fiddle z wersją demonstracyjną . To zapytanie da wynik:
| RESOURCE | CLIENTNAME | JAN2013 | FEB2013 | MAR2013 | APR2013 | MAY2013 |
---------------------------------------------------------------------------
| res1 | abc | 1000 | 2000 | 0 | 0 | 0 |
| res1 | def | 0 | 0 | 2000 | 0 | 0 |
| res2 | def | 1500 | 0 | 0 | 0 | 0 |
| res3 | ghi | 0 | 0 | 2500 | 0 | 0 |