2016-09-07 126 views
0

下面是我所处的场景。我有以下格式的数据。带有多列的SQL Server动态数据透视表

My source data

IssuedOn Country Sales Transactions 
------------------------------------------ 
29-Aug-16 India  40  8 
29-Aug-16 Australia 15  3 
29-Aug-16 Canada  15  3 
30-Aug-16 India  50  10 
30-Aug-16 Australia 25  5 
30-Aug-16 Canada  10  2 
31-Aug-16 India  100 25 
31-Aug-16 Australia 30  10 
31-Aug-16 Canada  55  12 

这是输出我找

Expected output

IssuedDate Australia Canada India TotalSales Transactionscount 
--------------------------------------------------------------------- 
29-Aug-16 15   15  40  70   14 
30-Aug-16 25   10  50  85   17 
31-Aug-16 30   55  100  185   47 

我已经能够转动的国家的数据,并获得了“总销售额”栏。但是,我无法获得“总交易”列的权利。

下面是生成源数据表的代码。如果有人能指导我,那真的会有所帮助。

Create Table tbl1 
(
    IssuedOn date, 
    Country varchar(100), 
    Sales bigint, 
    Transactions bigint 
) 


Insert into tbl1(IssuedOn, Country, Sales, Transactions) 
Values ('2016-08-29', 'India', 40, 8), 
     ('2016-08-29', 'Australia', 15, 3), 
     ('2016-08-29', 'Canada', 15, 3), 
     ('2016-08-30', 'India', 50, 10), 
     ('2016-08-30', 'Australia', 25, 5), 
     ('2016-08-30', 'Canada', 10, 2), 
     ('2016-08-31', 'India', 100, 25), 
     ('2016-08-31', 'Australia', 30, 10), 
     ('2016-08-31', 'Canada', 55, 12) 

select * 
from tbl1 

回答

0

以下是用于散装我的动态枢轴

Exec [prc-Pivot] 'tbl1','Country','sum(Sales)[]','IssuedOn','sum(Transactions)[Transactions],sum(Sales)[TotalSales]' 


IssuedOn Transactions TotalSales Australia Canada India 
2016-08-29 14    70   15   15  40 
2016-08-30 17    85   25   10  50 
2016-08-31 47    185   30   55  100 

存储过程

ALTER PROCEDURE [dbo].[prc-Pivot] (
    @Source varchar(1000),   -- Any Table or Select Statement 
    @PvotCol varchar(250),   -- Field name or expression ie. Month(Date) 
    @Summaries varchar(250),  -- aggfunction(aggValue)[optionalTitle] 
    @GroupBy varchar(250),   -- Optional additional Group By 
    @OtherCols varchar(500))  -- Optional Group By or aggregates 
AS 

--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]' 
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]' 

Set NoCount On 

Declare @Vals varchar(max),@SQL varchar(max); 
Set @Vals = '' 
Set @OtherCols= IsNull(', ' + @OtherCols,'') 
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '[email protected] end 
Create Table #TempPvot (Pvot varchar(100)) 
Insert Into #TempPvot 
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A') 
--Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),NULL) As [' + Pvot) From #TempPvot Order by Pvot 
    Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot) From #TempPvot Order by Pvot 
Drop Table #TempPvot 
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ') 
--Print @SQL 
Exec (@SQL) 
+0

非常感谢John。存储过程就像一个魅力。将不得不详细说明它的逻辑。同时,是否有一种简单的方法可以在结果集中将NULL值设置为0。 –

+0

@AnujDwivedi更新了我的答案以显示0而不是零 –

0

一个更详细的动态SQL查询的存储的过程,而不需要使用一个存储过程如下:

DECLARE @cols AS NVARCHAR(MAX); 
DECLARE @pivotSales AS NVARCHAR(MAX); 
DECLARE @sql AS NVARCHAR(MAX); 

SELECT @cols = ISNULL(@cols + ', ', '') + QUOTENAME(Country) 
FROM (SELECT DISTINCT Country FROM tbl1) AS Countries 

SET @pivotSales = N'SELECT IssuedOn, ' + @cols +' 
FROM (SELECT IssuedOn, Country, Sales FROM tbl1) AS sales 
PIVOT(SUM(Sales) FOR Country IN (' + @cols + ')) AS pvt'; 

SET @sql = ';WITH CTE_SalesPivot AS (
'[email protected]+' 
), 
CTE_SalesTotal AS (
    SELECT IssuedOn, SUM(Sales) AS [Grand Total] 
    FROM tbl1 
    GROUP BY IssuedOn 
), 
CTE_Transactions AS (
    SELECT IssuedOn, SUM(Transactions) AS [Transaction Count] 
    FROM tbl1 
    GROUP BY IssuedOn 
) 
SELECT CTE_SalesPivot.IssuedOn, ' + @cols + ', CTE_SalesTotal.[Grand Total], CTE_Transactions.[Transaction Count] 
FROM 
CTE_SalesPivot 
INNER JOIN CTE_SalesTotal ON CTE_SalesPivot.IssuedOn = CTE_SalesTotal.IssuedOn 
INNER JOIN CTE_Transactions ON CTE_SalesPivot.IssuedOn = CTE_Transactions.IssuedOn'; 

EXEC sp_executesql @sql; 

dynamic sql pivot query results

0

这里有一个简单的方法来使用聚合案例表达式。

DECLARE @cols NVARCHAR(MAX), 
     @sql NVARCHAR(MAX) 

SELECT @cols = STUFF((
     SELECT ',' + 'SUM(CASE WHEN Country = ''' + Country + ''' THEN Sales END) AS ' + QUOTENAME(Country) 
     FROM (SELECT DISTINCT Country FROM tbl1) t 
     ORDER BY Country 
     FOR XML PATH('') 
    ),1, 1, '') 

SET @sql = N' 
    SELECT IssuedOn, ' + @cols + ', 
      SUM(Sales) AS TotalSales, 
      SUM(Transactions) AS TransactionCount 
    FROM tbl1 
    GROUP BY IssuedOn 
' 
EXEC(@sql) 

这将生成一个应该看起来像这样的查询。

SELECT IssuedOn, 
     SUM(CASE WHEN Country = 'Australia' THEN Sales END) AS [Australia], 
     SUM(CASE WHEN Country = 'Canada' THEN Sales END) AS [Canada], 
     SUM(CASE WHEN Country = 'India' THEN Sales END) AS [India], 
     SUM(Sales) AS TotalSales, 
     SUM(Transactions) AS TransactionCount 
FROM tbl1 
GROUP BY IssuedOn