Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL:Използване на ISNULL с динамична ос

Бих настроил вашата заявка малко по-различно, защото въпреки че е динамична, тъй като имената на колоните се променят, вие все още сте кодирали твърдо броя на колоните.

Първо, бих използвал рекурсивен CTE, за да генерирам списъка с месеци/години, които искате да създадете.

DECLARE @startDate datetimeSET @startDate ='2013-01-01';с дати като( изберете @startdate datelist, 1 sp съюз всички изберете dateadd(month, 1, datelist), sp+1 от дати, където sp+1 <=5 -- променете това число 5 на броя месеци, от които се нуждаете) изберете sp, REPLACE(SUBSTRING(CONVERT(varchar(11), datelist, 13), 4, 8), ' ', '') MONTHANDYEARот дати 

Вижте SQL Fiddle с демонстрация . Това автоматично ще създаде вашия списък от 5 месеца с годината. Тогава не кодирате твърдо 5-те колони. Текущата ви заявка не е толкова гъвкава, колкото би могла да бъде. Какво ще стане, ако след това искате 12 месеца, ще трябва да промените кода си.

След като генерирате списъка с дати, бих го вмъкнал във временна таблица, за да можете да го използвате, за да получите колоните.

Кодът за получаване на списъка с колони е:

изберете @cols =STUFF((SELECT ',' + QUOTENAME(monthandyear) from #datesTemp group by monthandyear, sp order by sp FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') изберете @colNames =STUFF((SELECT ', isnull(' + QUOTENAME(monthandyear)+', 0) като '+QUOTENAME(monthandyear) от група #datesTemp от monthandyear, sp ред по sp FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') 

Вижте SQL Fiddle с демонстрация . Ще видите, че има две версии. Първият @cols получава списъка с колони, които ще бъдат използвани в опорната част . Вторият @colNames ще се използва в крайния SELECT списък за заместване на null стойности с нули.

След това събирате всичко заедно и кодът ще бъде:(Забележка:Използвам версия на моя отговор от вашия предишен въпрос )

DECLARE @cols AS NVARCHAR(MAX), @colNames AS NVARCHAR(MAX), @query AS NVARCHAR(MAX), @startDate datetimeSET @startDate ='2013-01-01';с дати като ( изберете @startdate списък с дати, 1 sp съюз всички изберете dateadd(месец, 1, списък с дати), sp+1 от дати, където sp+1 <=5 -- променете това число 5 на броя месеци, от които се нуждаете) изберете sp, REPLACE(SUBSTRING (КОНВЕРТИРАНЕ(varchar(11), datelist, 13), 4, 8), ' ', '') MONTHANDYEARinto #datesTempfrom datesselect @cols =STUFF((SELECT ',' + QUOTENAME(monthandyear) from #datesTemp group by monthandyear, sp ред по sp FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')select @colNames =STUFF((SELECT ', isnull(' + QUOTENAME(monthandyear)+', 0) като '+QUOTENAME(monthandyear) от #datesTemp групиране по monthandyear, sp ред по 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 от viewprojscheduling_group ) x осно (сума(FORECASTTOTAL) за месецигодина в (' + @cols + ') ) p 'execute(@query) 

Вижте SQL Fiddle с демонстрация . Тази заявка ще ви даде резултата:

<предварителен код>| РЕСУРСИ | ИМЕ НА КЛИЕНТА | ЯНУАРИ 2013 | ФЕВРУАРИ 2013 | МАРТ2013 | април 2013 | МАЙ 2013 |------------------------------------------------ ----------------------------| 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. PowerShell - Списък на всички SQL екземпляри в моята система?

  2. Параметризирайте SQL IN клауза

  3. Как да определите дали запис със специфичен тип данни IMAGE вече съществува в таблицата?

  4. Как да зацикля и анализира xml параметър в съхранена процедура на sql сървър

  5. Свържете се със SQL Server чрез PDO с помощта на драйвер на SQL Server