微软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 博客推荐栏中快速看到这些文章。

相关文章
相关标签/搜索