Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL:Verwendung von ISNULL mit dynamischem Pivot

Ich würde Ihre Abfrage etwas anders einrichten, da sie zwar dynamisch ist, da sich die Spaltennamen ändern, Sie die Anzahl der Spalten jedoch fest codiert haben.

Zuerst würde ich einen rekursiven CTE verwenden, um die Liste der Monate/Jahre zu generieren, die Sie erstellen möchten.

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

Siehe SQL-Geige mit Demo . Dadurch wird Ihre Liste der 5 Monate mit dem Jahr automatisch erstellt. Dann codieren Sie die 5 Spalten nicht fest. Ihre aktuelle Abfrage ist nicht so flexibel, wie sie sein könnte. Was passiert, wenn Sie dann 12 Monate wollen, müssen Sie Ihren Code ändern.

Sobald Sie die Datumsliste generiert haben, würde ich sie in eine temporäre Tabelle einfügen, damit Sie sie zum Abrufen der Spalten verwenden können.

Der Code zum Abrufen der Spaltenliste lautet:

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,'')

Siehe SQL-Geige mit Demo . Sie werden sehen, dass es zwei Versionen gibt. Der erste @cols Ruft die Liste der Spalten ab, die im pivot verwendet werden . Der zweite @colNames wird im abschließenden SELECT verwendet Liste zum Ersetzen von null Werte mit den Nullen.

Dann fügen Sie alles zusammen und der Code lautet:(Hinweis:Ich verwende eine Version meiner Antwort aus Ihrem vorherige Frage )

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)

Siehe SQL Fiddle mit Demo . Diese Abfrage liefert das Ergebnis:

| 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 |