Sql 服务器将列转换为行用零或现有值填充 NULL

Sql Server pivot columns into rows fill NULL with zero or existing value

我在 SQL 服务器中有 table 现在认为临时 table 如下:

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>

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

我想要如下所示的 Fill NULL value with Amount 这样的输出:

<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>

您的问题是您将 PeriodId 和 PeriodName 组合起来作为要在数据透视表中检查的值的方式。

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

PeriodName IN (' + @cols + ')

假设您将句点名称和 ID 组合用于特定目的,您应该做的是在 select

中创建相同的值
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