sql >> Databasteknik >  >> RDS >> Sqlserver

SQL:Använder ISNULL med dynamisk pivot

Jag skulle ställa in din fråga lite annorlunda eftersom den är dynamisk genom att kolumnnamnen ändras, men du har fortfarande hårdkodat antalet kolumner.

Först skulle jag använda en rekursiv CTE för att generera listan över månader/år som du vill skapa.

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

Se SQL-fiol med demo . Detta kommer att skapa din lista över de 5 månaderna med året automatiskt. Då hårdkodar du inte de 5 kolumnerna. Din nuvarande fråga är inte så flexibel som den skulle kunna vara. Vad händer om du sedan vill ha 12 månader, du kommer att behöva ändra din kod.

När du har skapat listan med datum, skulle jag infoga den i en tillfällig tabell så att du kan använda den för att hämta kolumnerna.

Koden för att få listan med kolumner är:

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

Se SQL-fiol med demo . Du kommer att se att det finns två versioner. Den första @cols hämtar listan över kolumner som kommer att användas i pivot . Den andra @colNames kommer att användas i den sista SELECT lista för att ersätta null värden med nollorna.

Sedan lägger du ihop allt och koden blir:(Obs! Jag använder en version av mitt svar från din föregående fråga )

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)

Se SQL-fiol med demo . Denna fråga ger dig resultatet:

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



  1. Python, Konvertera 9 tuppel UTC-datum till MySQL datumtidsformat

  2. Jämföra datum i MySQL och ignorera tidsdelen av ett DateTime-fält

  3. Hur exakt fungerar transaktioner med PHP PDO med samtidighet?

  4. Välj alla kolumner utom en i MySQL?