分享好友 数据库首页 频道列表

Oracle SQL函数pivot、unpivot转置函数实现行转列、列转行

数据库其他  2023-02-09 22:420
函数PIVOT、UNPIVOT转置函数实现行转列、列转行,效果如下图所示:

1.PIVOT为行转列,从图示的左边到右边

2.UNPIVOT为列转行,从图示的右边到左边

3.左边为纵表,结构简单,易扩展

4.右边为横表,展示清晰,方便查询

5.很多时候业务表为纵表,但是统计分析需要的结果如右边的横表,这时候就需要用到转置函数了

示例图表:


Pivot语法:

    SELECT ....
    FROM <table-expr>
       PIVOT
         (
          aggregate-function(<column>)
          FOR <pivot-column> IN (<value1>, <value2>,..., <valuen>)
            ) AS <alias>
    WHERE .....

注意:

FOR <pivot-column>

这个是不支持表达式的,如果需要,请通过子查询或者视图先预处理。

Pivot
例子1:先构造一个子查询,然后根据CHANNEL列进行转置,源表sales_view里面可能有很多列,不需要列先通过子查询过滤掉再进行转置。

另外转置后的列指定了别名,值是对amount_sold列的汇总。

    SELECT * FROM
      (SELECT product, channel, amount_sold
       FROM sales_view
       ) S PIVOT (SUM(amount_sold)
       FOR CHANNEL IN (3 AS DIRECT_SALES, 4 AS INTERNET_SALES, 
                       5 AS CATALOG_SALES, 9 AS TELESALES))
    ORDER BY product;
     
    PRODUCT                  DIRECT­_SALES  INTERNET_SALES  CATALOG_SALES  TELESALES
    ----------------------   ------------  --------------  -------------  ---------
    ...
    Internal 6X CD-ROM          229512.97        26249.55
    Internal 8X CD-ROM          286291.49        42809.44
    Keyboard Wrist Rest         200959.84        38695.36                   1522.73
    ... 


例子2:基于多列进行转置,下面例子是基于channel、quarter两列进行转置

    SELECT *
    FROM
         (SELECT product, channel, quarter, quantity_sold
          FROM sales_view
         ) PIVOT (SUM(quantity_sold)
                    FOR (channel, quarter) IN
                      ((5, '02') AS CATALOG_Q2,
                       (4, '01') AS INTERNET_Q1,
                       (4, '04') AS INTERNET_Q4,
                       (2, '02') AS PARTNERS_Q2,
                       (9, '03') AS TELE_Q3
                      )
                    );
     
    PRODUCT              CATALOG_Q2  INTERNET_Q1  INTERNET_Q4  PARTNERS_Q2   TELE_Q3
    -------              ----------  -----------  -----------  -----------   -------
    ...
    Bounce                                  347           632          954
    ...      
    Smash Up Boxing                         129           280          560
    ...  
    Comic Book Heroes                        47           155          275
    ...


例子3:对多列的值进行汇总计算,以下是基于channel例进行转置,然后对amount_sold和quantity_sold两列进行合计运算

    SELECT *
    FROM
         (SELECT product, channel, amount_sold, quantity_sold
          FROM sales_view
         ) PIVOT (SUM(amount_sold) AS sums,
                  SUM(quantity_sold) AS sumq
                  FOR channel IN (5, 4, 2, 9)
                   )
    ORDER BY product;
     
    PRODUCT                5_SUMS  5_SUMQ    4_SUMS   4_SUMQ      2_SUMS   2_SUMQ    9_SUMS   9_SUMQ
    -------------          ------  ------    ------   ------      ------   ------    ------   ------
    O/S Doc Set English                   142780.36     3081   381397.99     8044   6028.66      134
    O/S Doc Set French                     55503.58     1192   132000.77     2782   
    ... 


Unpivot
unpivot是pivot的相反操作,进行的是列转行


例子1:先看源表结构,for子句指定将(Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ)这4列转置为行,

for子句之前的quantity_sold是4列转置后的列名,

decode还定义了每列转置为行后新标示列的值,这个等下看第2个例子可以看到,也可以在 in 子句后面加 as 指定别名。

UNPIVOT INCLUDE NULLS 指定空值也进行转置,如果是EXCLUDE NULLS 将忽略空值。


    SELECT *
    FROM pivotedTable
    ORDER BY product;
     
    PRODUCT         Q1_SUMQ  Q1_SUMA  Q2_SUMQ  Q2_SUMA   Q3_SUMQ  Q3_SUMA   Q4_SUMQ    Q4_SUMA
    --------------- -------  -------  -------  --------  -------  --------  -------    ---------
    1.44MB External   6098   58301.33    5112   49001.56    6050   56974.3     5848     55341.28
    128MB Memory      1963  110763.63    2361  132123.12    3069  170710.4     2832    157736.6
    17" LCD           1492 1812786.94    1387 1672389.06    1591 1859987.66    1540   1844008.11


    SELECT product, DECODE(quarter, 'Q1_SUMQ', 'Q1', 'Q2_SUMQ', 'Q2', 'Q3_SUMQ', 'Q3',
       'Q4_SUMQ', 'Q4') AS quarter, quantity_sold
    FROM  pivotedTable
       UNPIVOT INCLUDE NULLS
           (quantity_sold
            FOR quarter IN (Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ))
    ORDER BY product, quarter;
     
    PRODUCT                          QUARTER      QUANTITY_SOLD
    -------                          --           -------------
    1.44MB External 3.5" Diskette    Q1             6098
    1.44MB External 3.5" Diskette    Q2             5112
    1.44MB External 3.5" Diskette    Q3             6050
    1.44MB External 3.5" Diskette    Q4             5848
    128MB Memory Card                Q1             1963
    128MB Memory Card                Q2             2361
    128MB Memory Card                Q3             3069
    128MB Memory Card                Q4             2832
    ...


例子2:转置多列的情况

    SELECT product, quarter, quantity_sold, amount_sold
    FROM  pivotedTable
       UNPIVOT INCLUDE NULLS
           (
            (quantity_sold, amount_sold)
            FOR quarter IN ((Q1_SUMQ, Q1_SUMA) AS 'Q1', (Q2_SUMQ, Q2_SUMA) AS 'Q2', (Q3_SUMQ, Q3_SUMA) AS 'Q3', (Q4_SUMQ, Q4_SUMA) AS 'Q4'))
    ORDER BY product, quarter;
     
    PRODUCT                          QU   QUANTITY_SOLD   AMOUNT_SOLD
    -----------------------------    --   -------------   ------------
    1.44MB External 3.5" Diskette    Q1            6098       58301.33
    1.44MB External 3.5" Diskette    Q2            5112       49001.56
    1.44MB External 3.5" Diskette    Q3            6050       56974.3
    1.44MB External 3.5" Diskette    Q4            5848       55341.28
    128MB Memory Card                Q1            1963      110763.63
    128MB Memory Card                Q2            2361      132123.12
    128MB Memory Card                Q3            3069      170710.4
    128MB Memory Card                Q4            2832      157736.6


总结,基本上按照语法套用即可,注意将源表非相关列先过滤掉,可是是子查询,也可以是视图。 
--------------------- 
作者:Seandba 
来源:CSDN 
原文:https://blog.csdn.net/seandba/article/details/72730657?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

查看更多关于【数据库其他】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
去重复的sql(Oracle) 去重复的英文
1.利用group by 去重复2.可以利用下面的sql去重复,如下  1) select id,name,sex from (select a.*,row_number() over(partition by a.id,a.set order by name) su from test a ) where su=1  2)select id,name,sex from (select a.*,row_number() over(p

0评论2023-02-10893

Oracle SQL七次提速技巧
以下SQL执行时间按序号递减。1,动态SQL,没有绑定变量,每次执行都做硬解析操作,占用较大的共享池空间,若共享池空间不足,会导致其他SQL语句的解析信息被挤出共享池。create or replace procedure proc1as beginfor i in 1..100000 loop    execute imme

0评论2023-02-10755

SQL ORACLE case when函数用法
case when 用法(1)简单case函数:格式:  case 列名   when 条件值1 then 选项1  when 条件值1 then 选项2......  else 默认值 end例如:  select   case job_level  when '1' then '1111'  when '2' then '2222'   when '3' then '3333

0评论2023-02-10564

mysql下如何执行sql脚本 执行SQL脚本
1.编写sql脚本,假设内容如下:  create database dearabao;  use dearabao;  create table niuzi (name varchar(20));  保存脚本文件,假设我把它保存在F盘的hello world目录下,于是该文件的路径为:F:\hello world\niuzi.sql2.执行sql脚本,可以有2种方法: 

0评论2023-02-10699

MySQL 5.7版本sql_mode=only_full_group_by问题
用到GROUP BY 语句查询时com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'col_user_6.a.START_TIME' which is not functionally dependent on colu

0评论2023-02-10973

Oracle迁移到MySQL性能下降的注意点 oracle数据库迁移需要注意的问题
背景:最近有较多的客户系统由原来由Oracle改造到MySQL后出现了性能问题CPU 100%,或是后台的CRM系统复杂SQL在业务高峰的时候出现堆积导致业务故障。在我的记忆里面淘宝最初从Oracle迁移到MySQL期间也遇到了很多SQL的性能问题,记忆最为深刻的子查询,当初的

0评论2023-02-10580

ORACLE中通过SQL语句(alter table)来增加、删除、修改字段
1.添加字段:alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ;2.添加备注:comment on column  库名.表名.字段名 is  '输入的备注';  如: 我要在ers_data库中  test表 document_type字段添加备注  comm

0评论2023-02-10584

MySQL与Oracle 差异比较之六触发器
触发器编号类别ORACLEMYSQL注释1创建触发器语句不同create or replace trigger TG_ES_FAC_UNIT  before insert or update or delete on ES_FAC_UNIT  for each rowcreate trigger `hs_esbs`.`TG_INSERT_ES_FAC_UNIT` BEFORE INSERT on `hs_esbs`.`es_fac_u

0评论2023-02-10914

mysql where条件:某时间字段为今天的sql语句
1.查询:注册时间为今天的所有用户数:select count(*) from customer where TO_DAYS(createtime) = TO_DAYS(NOW())2.获取当前时间到凌晨24点还有多长时间:(Java中可用于判断某时间是否为今天)final Calendar cal = Calendar.getInstance();    ca

0评论2023-02-10717

mysql中的sql
变量用户变量: 在用户变量前加@系统变量: 在系统变量前加@@运算符算术运算符有: +(加), -(减), * (乘), / (除) 和% (求模) 五中运算位运算符有:(位于), | (位或), ^ (位异或), ~ (位取反),(位右移),(位左移)比较运算符有: = (等于),(大于),(小于), = (大

0评论2023-02-10936

Oracle的HINT可以强制指定SQL的执行计划,比如选择索引、表的连接顺序以及表的连接方式等等。(转)
在Oracle中查看所有的表: select * from tab/dba_tables/dba_objects/cat; 看用户建立的表 :  select table_name from user_tables;  //当前用户的表 select table_name from all_tables;  //所有用户的表 select table_name from dba_tables;  //包

0评论2023-02-10857

Oracle sql 子字符串长度判断
Oracle sql 子字符串长度判断 select t.* from d_table t WHEREsubstr(t.col,1,1)='8' and instr(t.col,'/')0 and length(substr(t.col,1,instr(t.col,'/')))5; 字符串的前两位都是数字:select * from d_table t WHERE regexp_like(substr(t.col,1,2), '^[

0评论2023-02-10759

Oracle、MySql、Sql Server比对
MySql:廉价(部分免费):当前,MySQL採用双重授权(DualLicensed),他们是GPL和MySQLAB制定的商业许可协议。假设你在一个遵循GPL的***(开源)项目中使用MySQL,那么你能够遵循GPL协议免费使用MySQL。否则,你须要购买MySQLAB制定的那个商业许可协议。Windows $

0评论2023-02-10441

Oracle 存储过程,临时表,动态SQL测试
--创建事务级别的结果临时表create global temporary table tmp_yshy( c1 varchar2(100), c2 varchar2(100))on commit delete rows;--创建事务级别的存储sql语句的临时表create global temporary table tmp_sql( c1 varchar2(4000))on commit delete rows;测

0评论2023-02-10508

更多推荐