让我们直接进入它。这是代码
SELECT [prov], [201304], [201305], [201306], [201307]
FROM (
SELECT [prov], [arrival], [Amount]
FROM [tblSource]) up
PIVOT (SUM([Amount]) FOR [arrival] IN ([201304], [201305], [201306], [201307])) AS pvt
GO
它让我回到了一张如此可爱的桌子。我想知道如何获得每个“日期”列的总数以显示在附加的最后一行?
此外,基础表将添加更多数据,特别是更多日期。这意味着接下来将添加 201308 ,然后 201309 等
这意味着目前我必须每月修改上面的代码以反映添加内容。有没有办法解决?
答案 0 :(得分:2)
您可以使用动态SQL动态创建列,但是,我建议在为其设计的层中处理动态枢轴,例如SSRS或Excel。
DECLARE @SQL NVARCHAR(MAX) = '',
@SQL2 NVARCHAR(MAX) = '',
@SQL3 NVARCHAR(MAX) = '';
-- COMPILE THE UNIQUE VALUES FOR ARRIVAL THAT NEED TO BE PIVOTED
SELECT @SQL = @SQL + ',' + QUOTENAME(Arrival),
@SQL2 = @SQL2 + '+ISNULL(' + QUOTENAME(Arrival) + ', 0)',
@SQL3 = @SQL3 + ',' + QUOTENAME(Arrival) + ' = ISNULL(' + QUOTENAME(Arrival) + ', 0)'
FROM (SELECT DISTINCT Arrival FROM tblSource) s;
-- COMBINE THEM INTO A SINGLE QUERY
SET @SQL = 'SELECT [Prov]' + @SQL3 + ', [Total] = ' + STUFF(@SQL2, 1, 1, '') + '
FROM ( SELECT Arrival, Prov, Amount
FROM [tblSource]
UNION ALL
SELECT Arrival, ''Total'', SUM(Amount)
FROM [tblSource]
GROUP BY Arrival
) up
PIVOT
( SUM(Amount)
FOR Arrival IN (' + STUFF(@SQL, 1, 1, '') + ')
) pvt;';
-- EXECUTE THE QUERY
EXECUTE SP_EXECUTESQL @SQL;
这将创建并执行以下SQL:
SELECT [Prov],
[2013-01-01] = ISNULL([2013-01-01], 0),
[2013-02-01] = ISNULL([2013-02-01], 0),
[Total] = ISNULL([2013-01-01], 0) + ISNULL([2013-02-01], 0)
FROM ( SELECT Arrival, Prov, Amount
FROM [tblSource]
UNION ALL
SELECT Arrival, 'Total', SUM(Amount)
FROM [tblSource]
GROUP BY Arrival
) up
PIVOT
( SUM(Amount)
FOR Arrival IN ([2013-01-01],[2013-02-01])
) pvt;
子查询up
中的联合下方的查询在底部添加了总行,并且通过添加行中的所有列来简单地创建行总数。
<强> Example on SQL Fiddle 强>
我会再次强调,我真的建议在SQL之外处理这样的数据操作。
修改强>
使用UNION获取总行的另一种方法是使用GROUPING SETS
,如下所示:
DECLARE @SQL NVARCHAR(MAX) = '',
@SQL2 NVARCHAR(MAX) = '',
@SQL3 NVARCHAR(MAX) = '';
-- COMPILE THE UNIQUE VALUES FOR ARRIVAL THAT NEED TO BE PIVOTED
SELECT @SQL = @SQL + ',' + QUOTENAME(Arrival),
@SQL2 = @SQL2 + '+ISNULL(' + QUOTENAME(Arrival) + ', 0)',
@SQL3 = @SQL3 + ',' + QUOTENAME(Arrival) + ' = ISNULL(' + QUOTENAME(Arrival) + ', 0)'
FROM (SELECT DISTINCT Arrival FROM tblSource) s;
-- COMBINE THEM INTO A SINGLE QUERY
SET @SQL = 'SELECT [Prov]' + @SQL3 + ', [Total] = ' + STUFF(@SQL2, 1, 1, '') + '
FROM ( SELECT Arrival, Prov = ISNULL(Prov, 'Total'), Amount = SUM(Amount)
FROM [tblSource]
GROUP BY GROUPING SETS((Prov, arrival), (arrival))
) up
PIVOT
( SUM(Amount)
FOR Arrival IN (' + STUFF(@SQL, 1, 1, '') + ')
) pvt;';
-- EXECUTE THE QUERY
EXECUTE SP_EXECUTESQL @SQL;
答案 1 :(得分:0)
样本表
CREATE TABLE #TEMP([prov] VARCHAR(100),[arrival] INT, AMOUNT NUMERIC(12,2))
INSERT INTO #TEMP
SELECT 'A' [prov],'201304' [arrival],100 AMOUNT
UNION ALL
SELECT 'A' ,'201305' ,124
UNION ALL
SELECT 'A' ,'201306' ,156
UNION ALL
SELECT 'B' ,'201304' ,67
UNION ALL
SELECT 'B' ,'201305' ,211
UNION ALL
SELECT 'B' ,'201306' ,176
UNION ALL
SELECT 'C' ,'201304' ,43
UNION ALL
SELECT 'C' ,'201305' ,56
UNION ALL
SELECT 'C' ,'201306' ,158
<强> QUERY 强>
您可以使用ROLLUP获取行总数。有关ROLLUP的更多信息here
-- Get the columns for dynamic pivot
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + CAST([arrival] AS VARCHAR(50)) + ']',
'[' + CAST([arrival] AS VARCHAR(50)) + ']')
FROM (SELECT DISTINCT [arrival] FROM #TEMP) PV
ORDER BY [arrival]
-- Replace NULL value with zero
DECLARE @NulltoZeroCols NVARCHAR (MAX)
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+[arrival]+'],0) AS ['+[arrival]+']'
FROM (SELECT DISTINCT CAST([arrival] AS VARCHAR(50)) [arrival] FROM #TEMP)TAB
ORDER BY CAST([arrival]AS INT) FOR XML PATH('')),2,8000)
DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT [prov],' + @NullToZeroCols + ' FROM
(
SELECT
ISNULL([prov],''Total'')[prov],
SUM(AMOUNT)AMOUNT ,
ISNULL(CAST([arrival] AS VARCHAR(50)),''Total'')[arrival]
FROM #TEMP
GROUP BY [arrival],[prov]
WITH ROLLUP
) x
PIVOT
(
MIN(AMOUNT)
FOR [arrival] IN (' + @cols + ')
) p
ORDER BY CASE WHEN ([prov]=''Total'') THEN 1 ELSE 0 END,[prov]'
EXEC SP_EXECUTESQL @query
注意:如果您不想将NULL
替换为zero
,请在动态数据透视的外部查询中将@NullToZeroCols
替换为@cols