以水平格式显示 SQL 结果
Show SQL result in horizontal format
我只想改造这个:
Period | Department | Print | Copy
---------------------------------------
201601 | Dept 1 | 10 | 20
201601 | Dept 2 | 20 | 10
201602 | Dept 1 | 30 | 40
201602 | Dept 2 | 40 | 30
201603 | Dept 1 | 50 | 60
201603 | Dept 2 | 60 | 50
进入这个:
Department | 201601 Print | 201601 Copy | 201602 Print | 201602 Copy | 201603 Print | 201603 Copy
------------------------------------------------------------------------------------------
Dept 1 | 10 | 20 | 30 | 40 | 50 | 60
Dept 2 | 20 | 10 | 40 | 30 | 60 | 50
我试图用 PIVOT
构建脚本,但我不知道如何在列中显示每个时期的 "Print" 和 "Copy"。
此外,由于 'Period' 的值是未知的,因此我也不能在脚本中硬编码该值。
这是我的尝试:
SELECT [Department]
,[201601] AS [201601 Copy]
,[201602] AS [201602 Copy]
,[201603] AS [201603 Copy]
FROM
(SELECT [Copy], [Period], [Department] from #tempTable) AS ST
PIVOT
(SUM([Copy]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
这是使用我的示例数据创建 table 的脚本:
IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
DROP TABLE #tempTable
CREATE TABLE #tempTable(
[Period] varchar(50)
,[Department] varchar(50)
,[Print] int
,[Copy] int
)
INSERT INTO #tempTable VALUES
('201601', 'Dept 1', 10, 20)
,('201601', 'Dept 2', 20, 10)
,('201602', 'Dept 1', 30, 40)
,('201602', 'Dept 2', 40, 30)
,('201603', 'Dept 1', 50, 60)
,('201603', 'Dept 2', 60, 50)
感谢您提前回复。
回答
我研究了收到的答案并最终构建了以下脚本:
DECLARE @sql AS varchar(max);
SELECT @sql = 'SELECT [Department],' +
STUFF((
SELECT DISTINCT
',SUM(ISNULL(CASE [Period] WHEN ''' + [Period] + ''' THEN [Print] END, 0)) AS [' + [period] + ' Print]' +
',SUM(ISNULL(CASE [Period] WHEN ''' + [Period] + ''' THEN [Copy] END, 0)) AS [' + [period] + ' Copy]'
FROM #TempTable
FOR XML PATH('')
), 1, 1, '') +
'FROM #TempTable
GROUP BY [Department]';
PRINT @sql
EXEC(@sql);
您可以使用动态 sql 查询。
查询
declare @sql as varchar(max);
select @sql = 'select [Department],' + stuff((
select distinct ',max(case [Period] when ' + char(39) + [Period] + char(39) +
' then [Print] end) [' + [period] + ' Print]'
+ ',max(case [Period] when ' + char(39) + [Period] + char(39) +
' then [Copy] end) [' + [period] + ' Copy]'
from #TempTable
for xml path('')
), 1, 1, '');
select @sql += ' from #TempTable group by [Department];';
exec(@sql);
您可以使用 ISNULL() 和 SUM() 函数实现此目的。
SELECT [Department]
,SUM(ISNULL(CASE WHEN [Period]='201601' THEN [Print] END,0)) AS [201601 Print]
,SUM(ISNULL(CASE WHEN [Period]='201601' THEN Copy END,0)) AS [201601 Copy]
,SUM(ISNULL(CASE WHEN [Period]='201602' THEN [Print] END,0)) AS [201602 Print]
,SUM(ISNULL(CASE WHEN [Period]='201602' THEN Copy END,0)) AS [201602 Copy]
,SUM(ISNULL(CASE WHEN [Period]='201603' THEN [Print] END,0)) AS [201603 Print]
,SUM(ISNULL(CASE WHEN [Period]='201603' THEN Copy END,0)) AS [201603 Copy]
FROM #tempTable
GROUP BY [Department]
SELECT Department,SUM([201601Print])[201601 Print],SUM([201601Copy])[201601 Copy],SUM([201602Print])[201602 Print],
SUM([201602Copy])[201602 Copy],SUM([201603Print])[201603 Print],SUM([201603Copy])[201603 Copy] FROM (
SELECT [Department]
,[201601] AS [201601Copy]
,[201602] AS [201602Copy]
,[201603] AS [201603Copy]
,0 AS [201601Print]
,0 AS [201602Print]
,0 AS [201603Print]
FROM
(SELECT [Period],[Copy], [Department] from #tempTable) AS ST
PIVOT
(SUM([Copy]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
UNION ALL
SELECT [Department]
,0 AS [201601Copy]
,0 AS [201602Copy]
,0 AS [201603Copy]
,[201601] AS [201601Print]
,[201602] AS [201602Print]
,[201603] AS [201603Print]
FROM
(SELECT [Period],[Print], [Department] from #tempTable) AS ST
PIVOT
(SUM([Print]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
)A GROUP BY Department
另一个动态 SQL 使用数据透视表。
但是这个使用变量@Columns 来生成一个包含列名的字符串。
declare @Columns varchar(max);
set @Columns = STUFF((SELECT ', ' + QUOTENAME([Period] +' Print') + ', ' + QUOTENAME([Period] +' Copy') FROM #tempTable GROUP BY [Period] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)') ,1,1,'');
declare @SQL varchar(max);
set @SQL = 'select *
from (
select [Department], [Period] + '' Print'' as Title, [Print] as Value from #tempTable
union all
select [Department], [Period] + '' Copy'' as Title, [Copy] as Value from #tempTable
) q
pivot (sum(Value) for Title in ('+ @Columns +')) p;';
--select @SQL;
exec (@SQL);
我只想改造这个:
Period | Department | Print | Copy
---------------------------------------
201601 | Dept 1 | 10 | 20
201601 | Dept 2 | 20 | 10
201602 | Dept 1 | 30 | 40
201602 | Dept 2 | 40 | 30
201603 | Dept 1 | 50 | 60
201603 | Dept 2 | 60 | 50
进入这个:
Department | 201601 Print | 201601 Copy | 201602 Print | 201602 Copy | 201603 Print | 201603 Copy
------------------------------------------------------------------------------------------
Dept 1 | 10 | 20 | 30 | 40 | 50 | 60
Dept 2 | 20 | 10 | 40 | 30 | 60 | 50
我试图用 PIVOT
构建脚本,但我不知道如何在列中显示每个时期的 "Print" 和 "Copy"。
此外,由于 'Period' 的值是未知的,因此我也不能在脚本中硬编码该值。
这是我的尝试:
SELECT [Department]
,[201601] AS [201601 Copy]
,[201602] AS [201602 Copy]
,[201603] AS [201603 Copy]
FROM
(SELECT [Copy], [Period], [Department] from #tempTable) AS ST
PIVOT
(SUM([Copy]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
这是使用我的示例数据创建 table 的脚本:
IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
DROP TABLE #tempTable
CREATE TABLE #tempTable(
[Period] varchar(50)
,[Department] varchar(50)
,[Print] int
,[Copy] int
)
INSERT INTO #tempTable VALUES
('201601', 'Dept 1', 10, 20)
,('201601', 'Dept 2', 20, 10)
,('201602', 'Dept 1', 30, 40)
,('201602', 'Dept 2', 40, 30)
,('201603', 'Dept 1', 50, 60)
,('201603', 'Dept 2', 60, 50)
感谢您提前回复。
回答
我研究了收到的答案并最终构建了以下脚本:
DECLARE @sql AS varchar(max);
SELECT @sql = 'SELECT [Department],' +
STUFF((
SELECT DISTINCT
',SUM(ISNULL(CASE [Period] WHEN ''' + [Period] + ''' THEN [Print] END, 0)) AS [' + [period] + ' Print]' +
',SUM(ISNULL(CASE [Period] WHEN ''' + [Period] + ''' THEN [Copy] END, 0)) AS [' + [period] + ' Copy]'
FROM #TempTable
FOR XML PATH('')
), 1, 1, '') +
'FROM #TempTable
GROUP BY [Department]';
PRINT @sql
EXEC(@sql);
您可以使用动态 sql 查询。
查询
declare @sql as varchar(max);
select @sql = 'select [Department],' + stuff((
select distinct ',max(case [Period] when ' + char(39) + [Period] + char(39) +
' then [Print] end) [' + [period] + ' Print]'
+ ',max(case [Period] when ' + char(39) + [Period] + char(39) +
' then [Copy] end) [' + [period] + ' Copy]'
from #TempTable
for xml path('')
), 1, 1, '');
select @sql += ' from #TempTable group by [Department];';
exec(@sql);
您可以使用 ISNULL() 和 SUM() 函数实现此目的。
SELECT [Department]
,SUM(ISNULL(CASE WHEN [Period]='201601' THEN [Print] END,0)) AS [201601 Print]
,SUM(ISNULL(CASE WHEN [Period]='201601' THEN Copy END,0)) AS [201601 Copy]
,SUM(ISNULL(CASE WHEN [Period]='201602' THEN [Print] END,0)) AS [201602 Print]
,SUM(ISNULL(CASE WHEN [Period]='201602' THEN Copy END,0)) AS [201602 Copy]
,SUM(ISNULL(CASE WHEN [Period]='201603' THEN [Print] END,0)) AS [201603 Print]
,SUM(ISNULL(CASE WHEN [Period]='201603' THEN Copy END,0)) AS [201603 Copy]
FROM #tempTable
GROUP BY [Department]
SELECT Department,SUM([201601Print])[201601 Print],SUM([201601Copy])[201601 Copy],SUM([201602Print])[201602 Print],
SUM([201602Copy])[201602 Copy],SUM([201603Print])[201603 Print],SUM([201603Copy])[201603 Copy] FROM (
SELECT [Department]
,[201601] AS [201601Copy]
,[201602] AS [201602Copy]
,[201603] AS [201603Copy]
,0 AS [201601Print]
,0 AS [201602Print]
,0 AS [201603Print]
FROM
(SELECT [Period],[Copy], [Department] from #tempTable) AS ST
PIVOT
(SUM([Copy]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
UNION ALL
SELECT [Department]
,0 AS [201601Copy]
,0 AS [201602Copy]
,0 AS [201603Copy]
,[201601] AS [201601Print]
,[201602] AS [201602Print]
,[201603] AS [201603Print]
FROM
(SELECT [Period],[Print], [Department] from #tempTable) AS ST
PIVOT
(SUM([Print]) FOR [Period] IN ([201601],[201602],[201603])) AS PT
)A GROUP BY Department
另一个动态 SQL 使用数据透视表。
但是这个使用变量@Columns 来生成一个包含列名的字符串。
declare @Columns varchar(max);
set @Columns = STUFF((SELECT ', ' + QUOTENAME([Period] +' Print') + ', ' + QUOTENAME([Period] +' Copy') FROM #tempTable GROUP BY [Period] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)') ,1,1,'');
declare @SQL varchar(max);
set @SQL = 'select *
from (
select [Department], [Period] + '' Print'' as Title, [Print] as Value from #tempTable
union all
select [Department], [Period] + '' Copy'' as Title, [Copy] as Value from #tempTable
) q
pivot (sum(Value) for Title in ('+ @Columns +')) p;';
--select @SQL;
exec (@SQL);