Sql Server将列转换为行,使用零或现有值填充NULL

时间:2017-05-23 06:43:18

标签: sql sql-server pivot

我在SQL Server中有一个表,现在被认为是临时表,如下所示:

IF OBJECT_ID('tempdb..#Period') IS NOT NULL DROP TABLE #Period
IF OBJECT_ID('tempdb..#Account') IS NOT NULL DROP TABLE #account
IF OBJECT_ID('tempdb..#BudgetDetail') IS NOT NULL DROP TABLE #BudgetDetail

create table #Period([PeriodId] int,[PeriodName] varchar(50),CompanyID int)
insert into #Period values(1,'P1',100171)
insert into #Period values(2,'P2',100171)
insert into #Period values(3,'P3',100171)
select * from #Period

create table #account([AccountId] int,CompanyID int)
insert into #account values(1,100171)
insert into #account values(2,100171)
insert into #account values(3,100171)
select * from #account


create table #BudgetDetail([PeriodId] int,[AccountId] int,[Amount] money,CompanyID int)
insert into #BudgetDetail values(1,1,101,100171)
insert into #BudgetDetail values(1,2,100,100171)
insert into #BudgetDetail values(1,3,160,100171)
insert into #BudgetDetail values(2,1,110,100171)
insert into #BudgetDetail values(2,2,170,100171)
insert into #BudgetDetail values(2,3,0,100171)
insert into #BudgetDetail values(3,1,120,100171)
insert into #BudgetDetail values(3,2,180,100171)
insert into #BudgetDetail values(3,3,0,100171)

select * from #BudgetDetail

Below is my query :
    DECLARE @cols AS NVARCHAR(MAX), @query  AS NVARCHAR(MAX), @CompanyID int = 100171

 SELECT 
  @cols = STUFF((SELECT ',' + QUOTENAME([PeriodName] + ';' + 
  CONVERT(VARCHAR,[PeriodId]))
  FROM 
  #Period       
    FOR XML PATH(''), TYPE  
    ).value('.', 'NVARCHAR(MAX)'),1,1,'')  

 SET @query = 'SELECT *  FROM   
     (SELECT bd.AccountId, PeriodName, Amount    
      FROM          
     #Account acc LEFT JOIN
     #Period pr ON acc.CompanyID = pr.CompanyID LEFT JOIN
     #BudgetDetail bd ON acc.AccountId = bd.AccountID AND acc.CompanyID = 
      bd.CompanyID AND 
     pr.PeriodId = bd.PeriodId AND 
     pr.CompanyID = bd.CompanyID
    ) x  
    PIVOT
    (  
       SUM(Amount)
     FOR PeriodName IN (' + @cols + ')  
    ) p '
  print @query
  EXECUTE(@query);

当我运行以上查询时,我得到以下输出: 这是我的输出



<table style="width: 100%;" border="1">
<tbody>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;">&nbsp;AccountId</td>
<td style="height: 21px; width: 25.5771%;">&nbsp;P1;1</td>
<td style="height: 21px; width: 34.4229%;">&nbsp;P2;2</td>
<td style="height: 21px; width: 19%;">&nbsp;P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;">&nbsp;1</td>
<td style="height: 21px; width: 25.5771%;">&nbsp;NULL</td>
<td style="height: 21px; width: 34.4229%;">&nbsp;NULL</td>
<td style="height: 21px; width: 19%;">&nbsp;NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;">&nbsp;2</td>
<td style="height: 21px; width: 25.5771%;">&nbsp;NULL</td>
<td style="height: 21px; width: 34.4229%;">&nbsp;NULL</td>
<td style="height: 21px; width: 19%;">&nbsp;NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;">&nbsp;3</td>
<td style="height: 21px; width: 25.5771%;">&nbsp;NULL</td>
<td style="height: 21px; width: 34.4229%;">&nbsp;NULL</td>
<td style="height: 21px; width: 19%;">&nbsp;NULL</td>
</tr>
</tbody>
</table>
&#13;
&#13;
&#13;

上面的输出是正确的,但我想要Amount列值而不是NULL值,如下所示:

我希望输出像Fill NULL值和Amount,如下所示:

&#13;
&#13;
<table style="width: 100%;" border="1">
<tbody>
<tr style="height: 21px;">
<td style="height: 21px;">&nbsp;AccountId</td>
<td style="height: 21px;">&nbsp;P1;1</td>
<td style="height: 21px;">&nbsp;P2;2</td>
<td style="height: 21px;">&nbsp;P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;">&nbsp;1</td>
<td style="height: 21px;">&nbsp;101</td>
<td style="height: 21px;">&nbsp;110</td>
<td style="height: 21px;">&nbsp;120</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;">&nbsp;2</td>
<td style="height: 21px;">&nbsp;100</td>
<td style="height: 21px;">&nbsp;170</td>
<td style="height: 21px;">&nbsp;180</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;">&nbsp;3</td>
<td style="height: 21px;">&nbsp;160</td>
<td style="height: 21px;">&nbsp;0</td>
<td style="height: 21px;">&nbsp;0</td>
</tr>
</tbody>
</table>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

您的问题是将PeriodId和PeriodName组合在一起以便在数据透视表中检查的值。

你的@cols出现为[P1; 1],[P2; 2],[P3; 3] 但您的数据透视表仅使用PeriodName来检查这些值

PeriodName IN (' + @cols + ')

假设您正在为特定目的合并期间名称和ID,您应该做的是在选择

中创建相同的值
acc.AccountId, Amount, PeriodName + ';' + CONVERT(VARCHAR(10),pr.PeriodId) as PeriodKey

然后在数据透视表中使用此组合列。

FOR PeriodKey IN (' + @cols + ') 

结果动态sql是

SET @query = '
   SELECT
       * 
   FROM   
       (SELECT
           acc.AccountId, Amount, PeriodName + '';'' + CONVERT(VARCHAR(10),pr.PeriodId) as PeriodKey
        FROM          
           #Account acc
           LEFT JOIN #Period pr ON
               acc.CompanyID = pr.CompanyID
           LEFT JOIN #BudgetDetail bd ON
               acc.AccountId = bd.AccountID
           AND acc.CompanyID = bd.CompanyID
           AND pr.PeriodId = bd.PeriodId
           AND pr.CompanyID = bd.CompanyID
       ) x  
       PIVOT
       (  
           SUM(Amount)
           FOR PeriodKey IN (' + @cols + ')  
       ) p '

dbfiddle here