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%;"> AccountId</td>
<td style="height: 21px; width: 25.5771%;"> P1;1</td>
<td style="height: 21px; width: 34.4229%;"> P2;2</td>
<td style="height: 21px; width: 19%;"> P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 1</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 2</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 3</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> 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;"> AccountId</td>
<td style="height: 21px;"> P1;1</td>
<td style="height: 21px;"> P2;2</td>
<td style="height: 21px;"> P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 1</td>
<td style="height: 21px;"> 101</td>
<td style="height: 21px;"> 110</td>
<td style="height: 21px;"> 120</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 2</td>
<td style="height: 21px;"> 100</td>
<td style="height: 21px;"> 170</td>
<td style="height: 21px;"> 180</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 3</td>
<td style="height: 21px;"> 160</td>
<td style="height: 21px;"> 0</td>
<td style="height: 21px;"> 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 '
我在 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%;"> AccountId</td>
<td style="height: 21px; width: 25.5771%;"> P1;1</td>
<td style="height: 21px; width: 34.4229%;"> P2;2</td>
<td style="height: 21px; width: 19%;"> P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 1</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 2</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> NULL</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px; width: 19%;"> 3</td>
<td style="height: 21px; width: 25.5771%;"> NULL</td>
<td style="height: 21px; width: 34.4229%;"> NULL</td>
<td style="height: 21px; width: 19%;"> 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;"> AccountId</td>
<td style="height: 21px;"> P1;1</td>
<td style="height: 21px;"> P2;2</td>
<td style="height: 21px;"> P3;3</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 1</td>
<td style="height: 21px;"> 101</td>
<td style="height: 21px;"> 110</td>
<td style="height: 21px;"> 120</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 2</td>
<td style="height: 21px;"> 100</td>
<td style="height: 21px;"> 170</td>
<td style="height: 21px;"> 180</td>
</tr>
<tr style="height: 21px;">
<td style="height: 21px;"> 3</td>
<td style="height: 21px;"> 160</td>
<td style="height: 21px;"> 0</td>
<td style="height: 21px;"> 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 '