2017-03-07 118 views
8

我要的是如何将这些:显示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脚本,但我不知道如何在列中显示每个时段的“打印”和“复制”。 此外,由于'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 

这里是我的样本数据创建表的脚本:

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) 

感谢提前任何答复。

ANSWER

我研究收到的答复,并最终建立以下脚本:

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); 
+1

尽管表面相似到电子表格,SQL表是非常不同的东西 - 行和列一般都不是可以互换的。如果这纯粹是为了演示*的目的,最好在演示/报告层而不是数据库中做到这一点。 –

+0

发布您的答案是这样的 - 一个答案,并接受它,如果你觉得没有提供的答案解决了你的问题(更好)。 –

回答

5

您可以使用动态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); 
+0

工程就像一个魅力,非常感谢。我编辑了一下,并在我的问题中显示了我的最终脚本。 – pblyt

0

你可以做到这一点使用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] 
+0

感谢您的干净而简单的查询,但周期值将是未知的,这需要使用动态SQL。 – pblyt

+0

在这种情况下,您可以使用@Ullas代码! – balaji

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

使用一个枢轴另一个动态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); 
+0

感谢@LukStorms为您的整洁答案,但对不起,我选择了Ullas的答案,只使用1个变量。希望我可以选择两者作为答案! – pblyt