2013-10-08 82 views
9

SSIS有一個稱爲Pivot轉換的任務,它將列更改爲行,但是如何在使用t-sql的sql server中執行相同的任務?使用t-sql的樞軸轉換

這是我的示例表

location product qty 
----------------------- 
delhi  PEPSI 100 
GURGAON CAKE 200 
NOIDA  APPLE 150 
delhi  cake 250 

所以使用SSIS工具的軸心轉變ON位置爲的setkey和產品爲支點鍵後,O/P變

location pepsi cake apple 
delhi  100 null null 
GURGAON null 200 null 
NOIDA  null null 150 
delhi  null 250 null 

回答

9

使用PIVOT表運算符像這樣:

SELECT * 
FROM tablename 
PIVOT 
(
    MAX(qty) 
    FOR product IN([pepsi], [cake], [apple]) 
) as p; 

需要注意的是:

  • 我用MAX聚合函數與qty,如果你想獲得總和使用SUM或任何其他聚合函數。

  • 如果您想動態地執行此操作而不是手動編寫它們,則必須手動將列的值寫入以進行旋轉,但您必須使用動態SQL來執行此操作。

像這樣:

DECLARE @cols AS NVARCHAR(MAX); 
DECLARE @query AS NVARCHAR(MAX); 

select @cols = STUFF((SELECT distinct ',' + 
         QUOTENAME(product) 
         FROM tablename 
         FOR XML PATH(''), TYPE 
        ).value('.', 'NVARCHAR(MAX)') 
         , 1, 1, ''); 

SELECT @query = 'SELECT * 
FROM tablename 
PIVOT 
(
    MAX(qty) 
    FOR product IN(' + @cols + ')) AS p;'; 

execute(@query); 
+2

+1爲動態sql示例 – Dan

8

樞軸請求涉及三個邏輯處理階段,各具有相關聯的元素:

  1. 分組相
  2. 傳播階段
  3. 以及具有關聯聚合元素和聚合函數的聚合階段。

所以有需求,你的情況映射以下幾個階段:

  1. 分組已經對‘Location’
  2. 傳播進行了基於與最終列名‘Product’列的值來完成:「百事可樂」, '蛋糕', '蘋果'。
  3. ‘Qty’值將被彙總到生產交叉進行分組值和擴展元件

把標準樞軸聲明這些值:

SELECT ... 
FROM <source_table_or_table_expression> 
PIVOT(<agg_func>(<aggregation_element>) 
FOR <spreading_element> 
IN (<list_of_target_columns>)) AS <result_table_alias> 

您的查詢就會變成:

select location ,[PEPSI], [CAKE],[APPLE] 
from table1 
pivot (sum(qty) 
     for product 
     in ([PEPSI], [CAKE],[APPLE])) AS T 

重要的是要注意,使用PIVOT運算符,您不明確指定分組元素,刪除n在查詢中查詢GROUP BY。 PIVOT運算符隱式地將分組 元素指定爲源表(或表表達式)中未指定爲傳播元素或聚合元素的所有屬性。因此,您必須確保PIVOT運算符的源表除了分組,聚合和聚合元素之外沒有其他屬性,以便在指定傳播和聚合元素後,剩下的唯一屬性是您打算用作分組元素的屬性。您可以通過不直接將PIVOT運算符應用於原始表,而是轉換爲僅包含表示旋轉元素的屬性而不包含其他屬性的表表達式。

select location ,[PEPSI], [CAKE],[APPLE] 
from (select location,product,qty 
     from table1) as SourceTable 
     pivot (sum(qty) 
      for product 
      in ([PEPSI], [CAKE],[APPLE])) AS T 

希望這有助於更好地理解樞軸運算符!

編輯:添加UNPIVOT運算符的概念:

像樞轉時,Unpivoting還涉及到3個邏輯階段:

  1. 生產副本
  2. 提取元素
  3. 消除不相關的交叉記錄

將這些值放入標準的Unpivot語句中:

SELECT ... 
FROM <source_table_or_table_expression> 
UNPIVOT(<target_col_to_hold_source_col_values> 
FOR <target_col_to_hold_source_col_names> IN(<list_of_source_columns>)) AS 
<result_table_alias>; 

在你的情況,映射這些階段與要求:

  1. <target_col_to_hold_source_col_values> =,將持有源列的列名值 即:持列的值[Pepsi], [Cake],[Apple]即100,250 ...你想有一個單列爲:Qty
  2. <target_col_to_hold_source_col_names> =將保存源列名稱的列的名稱 ie:保存列名[Pepsi], [Cake],[Apple]您希望有一個單列a S:product
  3. <list_of_source_columns> =源表中的列名,你有興趣 即:[Pepsi], [Cake],[Apple]

您的查詢就會變成:

SELECT location,product,qty 
FROM #temp 
UNPIVOT(qty 
     FOR product 
     IN([Pepsi],[Cake],[Apple])) AS U; 

在那裏我有一個新增的結果,從上述數據透視聲明臨時表#temp

重要的一點需要注意的是: 未透視旋轉的表無法恢復原始表,因爲旋轉會導致聚合造成的詳細信息丟失。

+1

一個驚人的優秀帖子在pivoting,我希望我有更多的+ 1給你! – ConstantineK