2016-03-08 79 views
3

我已經搜索了該網站的所有可能的解決方案,但仍然無法找到我的樞軸問題的答案。多個字段上的SQL Server樞軸

我有一個包含以下數據的表格。

Portfolio | Date  | TotalLoans | ActiveLoans | TotalBalance 
-------------------------------------------------------------------- 
P1   | 2015-12-31 |  1,000 |   900 | 100,000.00 
P1   | 2015-11-30 |  1,100 |   800 | 100,100.00 
P1   | 2015-10-31 |  1,200 |   700 | 100,200.00 

我想創建一個支點與下面的輸出(僅在投資組合= P1)

Field  | 2015-12-31 | 2015-11-30 | 2015-10-31 | 
----------------------------------------------------- 
TotalLoans |  1,000 |  1,100 |  1,200 | 
ActiveLoans |  900 |  800 |  700 | 
TotalBalance | 100,000 | 100,100 | 100,200 | 

理想情況下,我找了一個動態的支點,但靜態查詢會做的一樣好我可以嘗試一個動態查詢。

回答

2

你先UNPIVOT你的表需要。您可以使用此查詢做到這一點:

SELECT Portfolio, [Date], Val, ColType 
FROM (SELECT Portfolio, 
      [Date], 
      TotalLoans, 
      ActiveLoans, 
      TotalBalance 
     FROM mytable 
     WHERE Portfolio = 'P1') AS srcUnpivot 
     UNPIVOT (
     Val FOR ColType IN (TotalLoans, ActiveLoans, TotalBalance)) AS unpvt 

輸出:

Portfolio Date  Val  ColType 
=============================================== 
P1   2015-12-31 1000  TotalLoans 
P1   2015-12-31 900  ActiveLoans 
P1   2015-12-31 100000 TotalBalance 
P1   2015-11-30 1100  TotalLoans 
P1   2015-11-30 800  ActiveLoans 
P1   2015-11-30 100100 TotalBalance 
P1   2015-10-31 1200  TotalLoans 
P1   2015-10-31 700  ActiveLoans 
P1   2015-10-31 100200 TotalBalance 

注:所有不樞轉場必須同一類型的。上面的查詢假設所有字段的類型爲int。如果情況並非如此,那麼你必須使用CAST

使用上面的查詢就可以申請PIVOT

SELECT Portfolio, ColType, [2015-12-31], [2015-11-30], [2015-10-31] 
FROM (
    ... above query here ... 
PIVOT (
    MAX(Val) FOR [Date] IN ([2015-12-31], [2015-11-30], [2015-10-31])) AS pvt 
+0

偉大的解決方案! +1從我身邊! – Shnugo

+0

我剛剛發佈了一個解決方案作爲動態SQL的答案,以避免手動編寫日期值。 – Shnugo

1

您需要使用Dyanmic SQL並構建它們。見的例子在http://social.technet.microsoft.com/wiki/contents/articles/17510.t-sql-dynamic-pivot-on-multiple-columns.aspx

下面是代碼

CREATE procedure CrossTab 
(
@select varchar(2000), 
@PivotCol varchar(100), 
@Summaries varchar(100), 
@GroupBy varchar(100), 
@OtherCols varchar(100) = Null 
) 

AS 
set nocount on 
set ansi_warnings off 
declare @sql varchar(8000) 

Select @sql = '' 

Select @OtherCols= isNull(', ' + @OtherCols,'') 

create table #pivot_columns (pivot_column_name varchar(100)) 

Select @sql='select ''' + replace(+ @PivotCol,',',''' as pivot_column_name union all select ''')+'''' 

insert into #pivot_columns 
exec(@sql) 

select @sql='' 

create table #pivot_columns_data (pivot_column_name varchar(100),pivot_column_data varchar(100)) 

Select @PivotCol='' 

Select @PivotCol=min(pivot_column_name) from #pivot_columns 

While @PivotCol>'' 
Begin 
    insert into #pivot_columns_data(pivot_column_name,pivot_column_data) 
    exec 
    (
    'select distinct ''' + @PivotCol +''' as pivot_column_name, convert(varchar(100),' + @PivotCol + ') as pivot_column_data from 
    ('+ 
     @select 
    +' 
    ) T' 
    ) 

    Select @PivotCol=min(pivot_column_name) from #pivot_columns where pivot_column_name>@PivotCol 
end 
select 
    @sql = @sql + ', ' + 
    replace(
     replace(
       @Summaries,'(','(CASE WHEN ' + Pivot_Column_name + '=''' + 
       pivot_column_data + ''' THEN ' 
        ), 
      ')[', ' END) as [' + pivot_column_data 
       ) 
from #pivot_columns_data 
order by pivot_column_name 

exec 
(
    'select ' + @GroupBy [email protected] [email protected] + 
    ' from (
    '+ 
     @select 
    +' 
    ) T 
    GROUP BY ' + @GroupBy 
) 
drop table #pivot_columns 
drop table #pivot_columns_data 

set nocount off 
set ansi_warnings on 

使用

EXEC CrossTab 
'SELECT LastName, OrderDate,shipcountry FROM northwind..Employees Employees 
INNER JOIN northwind..Orders Orders ON (Employees.EmployeeID=Orders.EmployeeID) ', 
'shipcountry,Year(OrderDate)', 
'Count(LastName)[]', 
'LastName' 
1

做到在以下幾個步驟:

if object_id('tempdb..#Data') is null 
    CREATE TABLE #Data 
     ([Portfolio] varchar(2), [Date] datetime, 
     [TotalLoans] decimal(9,2), [ActiveLoans] int, [TotalBalance] decimal(9,2)) 
    ; 

INSERT INTO #Data 
    ([Portfolio], [Date], [TotalLoans], [ActiveLoans], [TotalBalance]) 
VALUES 
    ('P1', '2015-12-31', 1000, 900, 100000.00), 
    ('P1', '2015-11-30', 1100, 800, 100100.00), 
    ('P2', '2015-10-31', 1200, 700, 100200.00) 
; 

WITH Transposed AS (
    --First reorganise the data, creating unions like this, by column 
    --Assumption is that you are not interested in [Portfolio] 
    SELECT [Portfolio], [Date], [TotalLoans] AS Amount, 'TotalLoans' Field FROM #Data 
    UNION SELECT [Portfolio], [Date], [ActiveLoans], 'ActiveLoans' FROM #Data 
    UNION SELECT [Portfolio], [Date], [TotalBalance], 'TotalBalance' FROM #Data 
) 
SELECT Field, [2015-10-31], [2015-11-30], [2015-12-31] --You can build a string with all the dates from your original data source 
FROM (
    SELECT [Date], [Field], [Amount] FROM Transposed 
) d 
PIVOT (
    MAX(Amount) 
    FOR [Date] IN ([2015-10-31], [2015-11-30], [2015-12-31]) 
) p 
2

這是Giorgos Betsos解決方案,動態SQL。這將無需明確寫入日期值。

請您:如果您喜歡這樣的話:不要請將此解決方案標記爲已接受,並將驗收設置爲Giorgos Betsos。努力工作!但你可以對它投票:-)

CREATE TABLE #tbl(Portfolio VARCHAR(10),[Date] DATE,TotalLoans DECIMAL(10,4),ActiveLoans DECIMAL(10,4),TotalBalance DECIMAL(10,4)); 
INSERT INTO #tbl VALUES 
('P1','20151231',1000,900,100000.00) 
,('P1','20151130',1100,800,100100.00) 
,('P1','20151031',1200,700,100200.00); 

DECLARE @pvtColumns VARCHAR(MAX)= 
(
    STUFF(
    (
     SELECT DISTINCT ',['+CONVERT(VARCHAR(10), [Date] ,126) + ']' 
     FROM #tbl 
     FOR XML PATH('') 
    ) 
    ,1,1,'') 
); 

DECLARE @cmd VARCHAR(MAX)= 
'SELECT Portfolio, ColType, ' + @pvtColumns + 
' FROM (
    SELECT Portfolio, [Date], Val, ColType 
    FROM (SELECT Portfolio, 
       [Date], 
       TotalLoans, 
       CAST(ActiveLoans AS DECIMAL(10,4)) AS ActiveLoans, 
       TotalBalance 
     FROM #tbl AS mytable 
     WHERE Portfolio = ''P1'') AS srcUnpivot 
     UNPIVOT (
      Val FOR ColType IN (TotalLoans, ActiveLoans, TotalBalance)) AS unpvt 
) AS srcPivot 
PIVOT (
    MAX(Val) FOR [Date] IN (' + @pvtColumns + ')) AS pvt'; 

EXEC (@cmd); 
+0

感謝您的有益修正。 –