sql >> Databáze >  >> RDS >> Sqlserver

SQL:Použití ISNULL s dynamickým pivotem

Váš dotaz bych nastavil trochu jinak, protože i když je dynamický v tom, že se názvy sloupců mění, stále máte pevně zakódovaný počet sloupců.

Nejprve bych použil rekurzivní CTE k vygenerování seznamu měsíců/roků, které chcete vytvořit.

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

Viz SQL Fiddle s ukázkou . Tím se automaticky vytvoří váš seznam 5 měsíců s rokem. Pak nekódujete napevno 5 sloupců. Váš aktuální dotaz není tak flexibilní, jak by mohl být. Co se stane, když budete chtít 12 měsíců, budete muset změnit svůj kód.

Jakmile vygenerujete seznam dat, vložím jej do dočasné tabulky, abyste ji mohli použít k získání sloupců.

Kód pro získání seznamu sloupců je:

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

Viz SQL Fiddle s ukázkou . Uvidíte, že existují dvě verze. První @cols získá seznam sloupců, které budou použity v pivot . Druhý @colNames bude použito ve finálním SELECT seznam nahradit null hodnoty s nulami.

Pak to dáte dohromady a kód bude:(Poznámka:Používám verzi své odpovědi z vašeho předchozí otázka )

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)

Viz SQL Fiddle s ukázkou . Tento dotaz vám dá výsledek:

| 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. #1064 -Máte chybu v syntaxi SQL; zkontrolujte příručku, která odpovídá verzi vašeho serveru MySQL

  2. Oracle Pro*C/OCI instalační obslužné programy pro SIGSEGV/SIGABRT a přátele – proč a jak je deaktivovat?

  3. Příklady MAKEDATE() – MySQL

  4. Převod čísla na slova v SQL