微軟BI 之SSIS 系列 - 在 SQL 和 SSIS 中實現行轉列的 PIVOT 透視操做

開篇介紹

記得筆者在 2006年左右剛開始學習 SQL Server 2000 的時候,遇到一個面試題就是行轉列,列轉行的操做,當時寫了很長時間的 SQL 語句最終仍是以失敗而了結。後來即便能寫出來,也是磕磕碰碰的,雖然很能鍛鍊 SQL 功底,每次都要掙扎一番,溺水的感受。記得SQL Server 2005 之後就有了 PIVOT 和 UNPIVOT 這兩個函數,能夠很是方便的實現行轉列和列傳行的操做,就再也不那麼掙扎了。後來,在一個 08 項目中,有一位新的女同事在改一個 ETL,發現 SSIS 包中有一個PIVOT 控件不知道怎麼用就叫我幫忙。雖然我以爲花點時間仍是能夠搞定的,可是爲了趕回家看一場球賽,找了一個不靠譜的接口就扔下她一我的給跑了。由於項目應該很急,每一個人壓力其實都很大,不記得是當天晚上就要交付仍是次日要交付。如今想一想,很內疚也很是敗人品,由於平時你們夥還都比較信任我,可是關鍵時刻跑了,確實有點不太負責任。今天正好整理到這一部分的筆記就想到了這個疙瘩,山東的那位妹子若是看到了,說聲對不起吧!html

SSIS 筆記整理到這幾個地方,就來總結一下 PIVOT 的使用,若是以前不會用的,看了這篇文章就能夠明白了。面試

測試代碼

IF OBJECT_ID('T040_PRODUCT_SALES') IS NOT NULL
DROP TABLE T040_PRODUCT_SALES
GO
CREATE TABLE T040_PRODUCT_SALES ( ID INT IDENTITY(1,1), ProductName VARCHAR(20), SaleMonth INT, SalesCount INT ) -- Inserting test data INSERT INTO T040_PRODUCT_SALES VALUES ('Bicycle',1,1), ('Shoes',2,2), ('Clothes',3,3), ('Books',4,4), ('Medicine',5,5), ('Drinks',6,6), ('Shoes',7,7), ('Books',1,2), ('Bicycle',1,3), ('Medicine',1,4), ('Clothes',1,5), ('Mobile Phone',1,6), ('Books',1,7), ('Medicine',1,8), ('Shoes',1,9), ('Bicycle',2,10) SELECT ProductName, SaleMonth, SUM(SalesCount) AS SalesCount FROM T040_PRODUCT_SALES GROUP BY ProductName, SaleMonth ORDER BY ProductName, SaleMonth

咱們須要實現的效果是按產品名稱,1月,2月,3月,4月,5月,6月 這七個列來顯示 SalesCount 的總數。函數

怎麼來實現這種行列轉換效果,只要把下面這個點就理解清楚,照着寫就能夠實現。學習

/****
SELECT 非透視列,
             [透視列 1] AS '列名1',
             [透視列 2] AS '列名2',
             [透視列 3] AS '列名3'
FROM (
        -- 源數據
        SELECT 非透視列,
               透視列值的來源列,
               須要聚合的值
        FROM 表
     )AS 別名
PIVOT
     (
        SUM(須要聚合的值)
        FOR 透視列值的來源列 IN ([透視列 1],[透視列 2],[透視列 3])
     )AS 別名
****/

對照上面的語法,咱們弄清楚這些對應關係:測試

  • 非透視列 - 通常是第一列,把效果想出來,ProductName 就是位於第一列,它是非透視列。
  • 透視列 - 就是須要由列變爲行的那些列,哪些行中的值須要做爲列來顯示? 1月 - 6月。
  • 透視列值的來源列 - 就是 SaleMonth,這列包含了 1月 - 6月的值。
  • 須要聚合的值 - 就是 SalesCount。

把這些需求理解了,就直接按照上面的這個語法就能夠實現了,沒有一點點多餘的代碼。spa

SELECT ProductName,
    ISNULL([1],0) AS '1', ISNULL([2],0) AS '2', ISNULL([3],0) AS '3', ISNULL([4],0) AS '4', ISNULL([5],0) AS '5', ISNULL([6],0) AS '6' FROM( SELECT ProductName, SaleMonth, SalesCount FROM T040_PRODUCT_SALES )AS Sales PIVOT ( SUM(SalesCount) FOR SaleMonth IN([1],[2],[3],[4],[5],[6]) )AS PIVOTBL

SSIS 中 Pivot 的實現

在數據流中添加一個 OLE DB Source 並配置源測試表。設計

添加一個 Pivot 控件。3d

對 Pivot 的配置code

Pivot Key - 透視列。透視列中的每個值(去重以後)將會造成一個新的列。htm

Set Key - 非透視列,須要和透視列一塊兒顯示的聚合列。

Pivot Value - Pivot Key 和 Set Key 一塊兒關聯的結果值。

之因此要選擇 Ignore un-matched pivot key values and report them after DataFlow execution 是由於:

Pivot 轉換控件是一個靜態的狀態控件,它須要清楚的知道在 Pivot Key 中有哪些肯定的值,它須要基於這些值來建立相應的輸出列。勾選中它並執行一次包以後,就能夠在 Progress/中看到惟一的 Pivot Key 列表,咱們在設計的階段就能夠經過這些列表上的值來肯定最終咱們須要建立的列。

好比,肯定了只須要 1月份 - 7月份的做爲新的輸出列,將這些只拷貝到指定的位置中,根據這些透視列來建立物理表中的透視列。

下面是建立以後的列的名稱。

這樣整個配置就完成了。

執行的時候查看一下數據,基本上反映出了行轉列的結構變化。這不過這些數據自己上看上去有一些重複,且沒有聚合。

所以咱們應該在查詢結果先把須要聚合好的內容聚合好,這樣在 PIVOT 轉換控件中就直接進行行,列轉換而不是轉換在聚合,這樣效率更高一些。

按照 ProductName 和銷售月份實現了對數據的行列轉換,數據信息的易讀性顯而易見。

固然也能夠看看 Show Advanced Editor 中的內容。

在這裏能夠看到 Pivot 轉換控件以前有 3 個數據源列,在通過 Pivot 轉換以後,其 Output Columns 變成 8 列向下輸出。

更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  若是以爲這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。

相關文章
相關標籤/搜索