zoukankan      html  css  js  c++  java
  • sql server 2008语言基础: 透视转换

    USE tempdb;
     
    IF OBJECT_ID('dbo.Orders', 'U') IS NOT NULL DROP TABLE dbo.Orders;
    GO
     
    CREATE TABLE dbo.Orders
    (
      orderid   INT        NOT NULL,
      orderdate DATE       NOT NULL, -- prior to SQL Server 2008 use DATETIME
      empid     INT        NOT NULL,
      custid    VARCHAR(5) NOT NULL,
      qty       INT        NOT NULL,
      CONSTRAINT PK_Orders PRIMARY KEY(orderid)
    );
     
    INSERT INTO dbo.Orders(orderid, orderdate, empid, custid, qty)
    VALUES
      (30001, '20070802', 3, 'A', 10),
      (10001, '20071224', 2, 'A', 12),
      (10005, '20071224', 1, 'B', 20),
      (40001, '20080109', 2, 'A', 40),
      (10006, '20080118', 1, 'C', 14),
      (20001, '20080212', 2, 'B', 12),
      (40005, '20090212', 3, 'A', 10),
      (20002, '20090216', 1, 'C', 20),
      (30003, '20090418', 2, 'B', 15),
      (30004, '20070418', 3, 'C', 22),
      (30007, '20090907', 3, 'D', 30);
    image
    select empid,custid,SUM(qty) SumQty from Orders
    group by empid, custid

    得到image每个员工在每个客户身上一共有多少个产品数量. 看到这个图. 如果我们想得到下面这个图呢

    image这就是行转列的问题了.

    传统方法.

    with t as(
    select empid,custid,SUM(qty) SumQty from Orders
    group by empid, custid
    )
    ----传统方法.
    select empid,
    max(case when custid='A' then qty else 0 end) A,
    max(case when custid='B' then qty else 0 end) B,
    max(case when custid='C' then qty else 0 end) C,
    max(case when custid='D' then qty else 0 end) D
     from Orders group by empid

    pivot透视法.

    --pivot运算符. 也是在查询的from子句的上下文中执行操作. 它对某个源表或者表表达式进行操作, 透视数据.
    --再返回一个结果表.  三个步骤, 分组, 扩展, 聚合.
    --在pivot运算符的圆括号内要指定聚合函数(本例为sum), 聚合元素(qty), 扩展元素(custid),
    --以及目标列名称的列表. 在pivot运算符的圆括号后面, 可以为结果表指定一个别名.

    select empid, A,B,C,D,e from 
    ( 
    select empid,custid, qty from Orders
    ) as t 
    pivot(sum(qty) for custid in(A,B,C,D,e))
    as p;
    这时候, 我们可能会问.
    select empid, A,B,C,D,e from 
    Orders
    pivot(sum(qty) for custid in(A,B,C,D,e))
    as p;

    这样写行不行呢?

    我们来运行一下. 得到image. 并没有按empid分组.

    image

    可以这么理解. 如果直接用order表作为源表. 那么直接就用order表的每一行进行分组. 得到的自然是最小粒度的行.

    ( select empid,custid, qty from Orders ) as t  作为源表. 那么就是用empid, custid, qty三列有资格作为分组列.

    可是在下文的代码里. custid成为了扩展列. qty成为了聚合列. 那么还有一个分组列呢. 自然就是empid了.

    于是. 就达到了目标.

    练习

    /*
     普通行列转换
     (爱新觉罗.毓华 2007-11-18于海南三亚)
     
    假设有张学生成绩表(tb)如下:
     Name Subject Result
     张三 语文  74
     张三 数学  83
     张三 物理  93
     李四 语文  74
     李四 数学  84
     李四 物理  94
     */
     
    -------------------------------------------------------------------------
     /*
     想变成 
     姓名         语文        数学        物理          
     ---------- ----------- ----------- ----------- 
     李四         74          84          94
     张三         74          83          93
     */
     
    create table tb
     (
        Name    varchar(10) ,
        Subject varchar(10) ,
        Result  int
     )
     
    insert into tb(Name , Subject , Result) values('张三' , '语文' , 74)
     insert into tb(Name , Subject , Result) values('张三' , '数学' , 83)
     insert into tb(Name , Subject , Result) values('张三' , '物理' , 93)
     insert into tb(Name , Subject , Result) values('李四' , '语文' , 74)
     insert into tb(Name , Subject , Result) values('李四' , '数学' , 84)
     insert into tb(Name , Subject , Result) values('李四' , '物理' , 94)
     go
     
    --静态SQL,指subject只有语文、数学、物理这三门课程。
     select name 姓名,
       max(case subject when '语文' then result else 0 end) 语文,
       max(case subject when '数学' then result else 0 end) 数学,
       max(case subject when '物理' then result else 0 end) 物理
     from tb
     group by name
     /*
     姓名         语文        数学        物理          
     ---------- ----------- ----------- ----------- 
     李四         74          84          94
     张三         74          83          93
     */
     
    首先写出pivot源表的表表达式.select name,result, [subject] from tb. 其中 name是分组列, result是聚合列. subject是扩展列.
    image
    pivot(语法) as 临时表明.
    完成最后的select:  select name , 语文,数学,物理..  得到
    select name , 语文,数学,物理
    from(
    select name,result, [subject] from tb
    ) z pivot(max(result) for [subject] in (语文,数学,物理)) as p
    
     
    本人在长沙, 有工作可以加我QQ4658276
  • 相关阅读:
    机器学习100天——实现简单线性回归(第二天)
    一起学Hive——详解四种导入数据的方式
    一起学Hive——创建内部表、外部表、分区表和分桶表及导入数据
    Apache Pulsar——企业级消息订阅系统介绍
    一起学Hadoop——实现两张表之间的连接操作
    一起学Hadoop——文件的上传、分发与打包
    机器学习100天——数据预处理(第一天)
    java调用python程序以及向python程序传递参数
    页面中查询模块的设计与实现思路
    以前的博客内容迁至CSDN,博客名不变,以后博客将在两个平台同步更新
  • 原文地址:https://www.cnblogs.com/jianjialin/p/2442573.html
Copyright © 2011-2022 走看看