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
  • 相关阅读:
    [super dealloc]内存释放的先后顺序
    NSString的常用方法
    Xcode开发技巧之code snippets(代码片段)
    关于oc运行时 isa指针详解
    ios快捷键
    自动释放池的使用
    【字典树】统计难题
    数据结构实验之图论五:从起始点到目标点的最短步数(BFS)
    字典树模板
    数据结构实验之串三:KMP应用
  • 原文地址:https://www.cnblogs.com/jianjialin/p/2442573.html
Copyright © 2011-2022 走看看