sql >> Database >  >> RDS >> Sqlserver

SQL:ISNULL gebruiken met dynamische pivot

Ik zou je zoekopdracht iets anders instellen, want hoewel het dynamisch is omdat de kolomnamen veranderen, heb je het aantal kolommen nog steeds hard gecodeerd.

Ten eerste zou ik een recursieve CTE gebruiken om de lijst met maanden/jaren te genereren die u wilt maken.

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

Zie SQL Fiddle met demo . Dit gaat automatisch uw lijst van de 5 maanden met het jaar maken. Dan codeer je de 5 kolommen niet hard. Uw huidige vraag is niet zo flexibel als het zou kunnen zijn. Wat gebeurt er als je dan 12 maanden wilt, je zult je code moeten wijzigen.

Zodra u de lijst met datums heeft gegenereerd, zou ik deze in een tijdelijke tabel invoegen, zodat u deze kunt gebruiken om de kolommen te krijgen.

De code om de lijst met kolommen te krijgen is:

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

Zie SQL Fiddle met demo . U zult zien dat er twee versies zijn. De eerste @cols krijgt de lijst met kolommen die zullen worden gebruikt in de pivot . De tweede @colNames wordt gebruikt in de laatste SELECT lijst om de null . te vervangen waarden met nullen.

Dan zet je alles bij elkaar en de code zal zijn:(Opmerking:ik gebruik een versie van mijn antwoord van je vorige vraag )

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)

Zie SQL Fiddle met demo . Deze zoekopdracht geeft je het resultaat:

| 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. MySql:BESTELLEN DOOR ouder en kind

  2. oracle diff:hoe twee tabellen te vergelijken?

  3. dubbele velden in een join uitsluiten

  4. Verbind verschillende Windows-gebruikers in SQL Server Management Studio (2005 of later)