使用数字列数更改的数据透视表

时间:2015-09-17 15:07:25

标签: sql sql-server sql-server-2012

我正在使用SQL Server 2012&我有两张桌子。

 tblStocks                     tblFunds

 fundCode nvarchar             fundCode nvarchar
 stockID  nvarchar             fundType nvarchar
 shares int

我将在解释之前展示以下数据的示例,因为它可能更容易首先看到示例。

 tblStocks
 fundCode    stockID   shares
 abcd        m33       20
 abcd        b22       10
 abcd        c33       5
 abcd        p99       6
 xyzu        m33       10
 xyzu        b22       8
 xyzu        w88       12

 tblFunds
 fundCode   fundType
 abcd       EQ
 xyzu       EQ

所以请注意,tblStocks的资金可以拥有多只股票,但每只股票在该基金中都是独一无二的,即abcd不会持有两只m33股票。

另请注意abcd和xyzu可以持有相同的股票,因此两者都可以持有m33。

以下是我希望看到的结果。所以我有一个独特的股票清单,然后对于每个基金我都拥有该基金的股票数量。所以我知道我需要在这里使用一个支点(这是我知道的唯一方法)。然而,增加的复杂性(对我而言)是不同基金的数量并不总是两个,所以我不知道如何在sql server中编码?

stockID    abcd    xyzu
m33        20      10
b22        10      8
c33        5       0
p99        6       0
w88        0       12

1 个答案:

答案 0 :(得分:3)

您需要使用动态SQL来创建pivot语句。

类似的东西:

DECLARE @SQL varchar(MAX)
DECLARE @columns varchar(MAX)

SET @columns = 'column1, column2, column3' -- etc.

SET @SQL  = 'SELECT * FROM () PIVOT (
' + @columns + '
)'

EXECUTE(@SQL)

因此,您需要获取列(确保没有NULL值)

DECLARE @columns varchar(MAX) 


SELECT @columns = COALESCE(@columns + ', ', '') + QUOTENAME(fundCode)
FROM tblFunds 
WHERE fundCode IS NOT NULL 

PRINT @columns

然后像这样完成查询:

DECLARE @SQL nvarchar(MAX) 
DECLARE @columns nvarchar(MAX) 
DECLARE @columnsOrder nvarchar(MAX) 


SELECT @columns = COALESCE(@columns + N', ', N'') + QUOTENAME(fundCode) 
FROM tblFunds


SELECT @columnsOrder = COALESCE(@columnsOrder + N', ', N'') + QUOTENAME(fundCode) + N' DESC'  
FROM tblFunds


SET @SQL = N'
SELECT * FROM  
(
    SELECT 
         stockid 
        ,fundCode 
        ,shares 
    FROM tblStocks 
) AS dataToPivot 
PIVOT 
(
   SUM(shares)
   FOR fundCode IN (' + @columns + N')
) AS p 

ORDER BY ' + @columnsOrder + N' 
' 


-- PRINT @columns
-- PRINT @columnsOrder
-- PRINT @SQL 
EXECUTE(@SQL) 

你仍然应该抓住tblFunds中没有条目的情况(在一开始,查询运行正常,但不返回任何值,也没有空表)...

我还会创建另外两个测试条目,一个用撇号,另一个用方括号[]

INSERT INTO tblFunds (fundCode, fundType) VALUES (N'ACME [US]', N'EQ');
INSERT INTO tblFunds (fundCode, fundType) VALUES (N'Goa''uld Charity Fund', N'EQ');

当你在列名上运行QUOTENAME时,你会发现它的工作正常。