Показать результат 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)
Спасибо за любой ответ заранее.
ответ
Я изучил полученные ответы и, наконец, построил следующий скрипт:
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);
4 ответов
можно использовать динамический 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);
другой динамический SQL, который использует pivot.
Но этот использует переменную @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);
вы можете достичь этого, используя функции 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