Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL:Używanie ISNULL z dynamicznym przestawem

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 |



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Uprawnienia dla PSExec uruchamiane z zadania SQL

  2. Wewnętrzne elementy SQL Server:Plan Caching Pt. II – Ponowna kompilacja planów

  3. Jak utworzyć alias typu danych zdefiniowanego przez użytkownika w SQL Server przy użyciu T-SQL

  4. hibernacja inżynierii wstecznej w Netbeans nie może znaleźć tabel SQL Server

  5. Kiedy sortowanie programu SQL Server jest przewijane?