PIVOT列并用0替换空值

时间:2017-07-10 16:03:23

标签: sql sql-server sql-server-2008 tsql

我正在使用以下SQL来PIVOT数据当这个sql EXECUTE我得到结果但我也得到Null值时没有特定日期的数据,因为列是随机生成我无法找到用0替换NULL值的方法。有人请帮助我。任何帮助都会很棒。

drop table #Daysoftheweek

create table #Daysoftheweek
(department varchar(10),TotalUtilized int,DayoftheWeek varchar(30))

insert into #Daysoftheweek
VALUES ('ER','0',convert (varchar(30),GETDATE()-1,120))
,('ICU','1',convert (varchar(30),GETDATE()-1,120))
,('ICU','1',convert (varchar(30),GETDATE()-2,120))
,('CICU','0',convert (varchar(30),GETDATE()-3,120))

DECLARE @cols NVARCHAR (MAX)
DECLARE @query NVARCHAR(MAX)

SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR, DayoftheWeek, 106) + ']', 
               '[' + CONVERT(NVARCHAR, DayoftheWeek, 106) + ']')
               FROM    (SELECT DISTINCT DayoftheWeek FROM #Daysoftheweek) PV  
               ORDER BY DayoftheWeek
SET @query = '           
              SELECT * FROM 
             (
                 SELECT * FROM #Daysoftheweek
             ) x
             PIVOT 
             (
                 avg(TotalUtilized)
                 FOR DayoftheWeek IN (' + @cols + ')
            ) p      

            '  
EXEC SP_EXECUTESQL @query

3 个答案:

答案 0 :(得分:1)

您需要与select列列表分开生成pivot()列的代码。

我已将您现有的代码转换为使用stuff() with select ... for xml path ('') method of string concatenation

declare @cols nvarchar (max), @selectcols nvarchar(max), @query nvarchar(max);

set @cols = stuff((
  select distinct ', ' + quotename(convert(nvarchar(30),DayoftheWeek,106))
  from #Daysoftheweek
  for xml path (''), type).value('(./text())[1]','nvarchar(max)')
  ,1,2,'');
set @selectcols = (
  select distinct char(10)+'  , ' + quotename(convert(nvarchar(30),DayoftheWeek,106))
    +' = isnull('     + quotename(convert(nvarchar(30),DayoftheWeek,106)) + ',0)'
  from #Daysoftheweek
  for xml path (''), type).value('(./text())[1]','nvarchar(max)')
set @query = '
select 
    Department '+@selectcols +' 
from (select * from #Daysoftheweek) x
pivot (avg(TotalUtilized)for DayoftheWeek in (' + @cols + ')) p';

select CodeGenerated = @query;
exec sp_executesql @query;

rextester演示:http://rextester.com/DQET60056

代码生成:

select 
    Department 
  , [2017-07-07 18:17:25] = isnull([2017-07-07 18:17:25],0)
  , [2017-07-08 18:17:25] = isnull([2017-07-08 18:17:25],0)
  , [2017-07-09 18:17:25] = isnull([2017-07-09 18:17:25],0) 
from (select * from #Daysoftheweek) x
pivot (avg(TotalUtilized)for DayoftheWeek in ([2017-07-07 18:17:25], [2017-07-08 18:17:25], [2017-07-09 18:17:25])) p

返回:

+------------+---------------------+---------------------+---------------------+
| Department | 2017-07-07 18:17:25 | 2017-07-08 18:17:25 | 2017-07-09 18:17:25 |
+------------+---------------------+---------------------+---------------------+
| cicu       |                   0 |                   0 |                   0 |
| er         |                   0 |                   0 |                   0 |
| icu        |                   0 |                   1 |                   1 |
+------------+---------------------+---------------------+---------------------+

答案 1 :(得分:1)

这也有效。我在您的查询中创建了一个CTE,并传入了一个要使用的选择字符串。

CREATE TABLE #Daysoftheweek
(department VARCHAR(10),TotalUtilized INT,DayoftheWeek VARCHAR(30))

--Put dates into varchar variable
DECLARE @date1 VARCHAR(30) = CONVERT (VARCHAR(30),GETDATE()-1,120)
DECLARE @date2 VARCHAR(30) = CONVERT (VARCHAR(30),GETDATE()-2,120)
DECLARE @date3 VARCHAR(30) = CONVERT (VARCHAR(30),GETDATE()-3,120)

--Create Select string for later
DECLARE @selectString VARCHAR(MAX) = 'department,[' + 
                            @date3 + '] = isnull([' + @date3 + '],0), [' + 
                            @date2 + '] = isnull([' + @date2 + '],0), [' +
                            @date1 + '] = isnull([' + @date1 + '],0)'

INSERT INTO #Daysoftheweek
VALUES ('ER','0',@date1)
,('ICU','1',@date1)
,('ICU','1',@date2)
,('CICU','0',@date3)

DECLARE @cols NVARCHAR (MAX)
DECLARE @query NVARCHAR(MAX)

SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR, DayoftheWeek, 106) + ']', 
               '[' + CONVERT(NVARCHAR, DayoftheWeek, 106) + ']')
               FROM    (SELECT DISTINCT DayoftheWeek FROM #Daysoftheweek) PV  
               ORDER BY DayoftheWeek
--Query with CTE and using @selectString created above
SET @query = 'WITH preselect AS (          
              SELECT * FROM 
             (
                 SELECT * FROM #Daysoftheweek
             ) x
             PIVOT 
             (
                 avg(TotalUtilized)
                 FOR DayoftheWeek IN (' + @cols + ')
            ) p )

            SELECT ' + @selectString + '
            FROM preselect'  

EXEC SP_EXECUTESQL @query

DROP TABLE #Daysoftheweek

答案 2 :(得分:0)

您需要将Coalesce应用于选择列表中的透视列。所以对代码生成进行一些调整就可以了解

(2)