Oracle Pivot 多列

Posted

技术标签:

【中文标题】Oracle Pivot 多列【英文标题】:Oracle Pivot multiple columns 【发布时间】:2020-04-17 11:39:25 【问题描述】:

我的数据如下所示:

age sex value   option              
1   f   0.019500000000000000    OPTION_1                
2   f   0.019500000000000000    OPTION_1                
3   f   0.019500000000000000    OPTION_1                
4   f   0.019500000000000000    OPTION_1                
5   f   0.019500000000000000    OPTION_1                        
1   m   0.081000000000000002    OPTION_1                
2   m   0.081000000000000002    OPTION_1                
3   m   0.081000000000000002    OPTION_1                
4   m   0.081000000000000002    OPTION_1                
5   m   0.081000000000000002    OPTION_1                
1   f   0.159000000000000002    OPTION_2                
2   f   0.107999999999999999    OPTION_2                
3   f   0.073500000000000009    OPTION_2                
4   f   0.063000000000000000    OPTION_2                
5   f   0.059999999999999997    OPTION_2                            
1   m   0.307499999999999996    OPTION_2                
2   m   0.220500000000000002    OPTION_2                
3   m   0.156000000000000000    OPTION_2                
4   m   0.133500000000000008    OPTION_2                
5   m   0.115500000000000005    OPTION_2                        

我可以透视这些数据来获取

age k   m
1   0.0195  0.081
2   0.0195  0.081
3   0.0195  0.081
4   0.0195  0.081
5   0.0195  0.081

但这仅适用于 OPTION_1。 问题是 - 我可以在一个查询 输出类似

age k_option_1  m_option_1 k_option_2   m_option_2
1   0.0195  0.081   0.1590  0.307
2   0.0195  0.081   0.1079  0.220
3   0.0195  0.081   0.0735  0.156
4   0.0195  0.081   0.0630  0.133
5   0.0195  0.081   0.0599  0.115

并将结果添加到选项 OPTION_2?

【问题讨论】:

是的,你可以。炖阿什顿向您展示了如何。 (Gordon Linoff 也这样做了 - 他向您展示的是,在 Oracle 11.1 引入 PIVOT 运算符之前,过去是如何进行旋转的。最好两种方式都学习,因为它们都很有价值。)唯一的问题——这是一个严肃的问题——是否只有两种可能的选择。如果您可以拥有OPTION_3OPTION_4 等值,并且您想要一个取决于数据的结果,那将更加复杂和困难。 sex 没有这样的问题 - 只有两个可能的值,事先知道(没有先看到数据)。 【参考方案1】:

只使用条件聚合:

select age,
       max(case when sex = 'f' and option = 1 then value end) as f_option_1,
       max(case when sex = 'm' and option = 1 then value end) as m_option_1,
       max(case when sex = 'f' and option = 2 then value end) as f_option_2,
       max(case when sex = 'm' and option = 2 then value end) as m_option_2
from t
group by age;

【讨论】:

【参考方案2】:

如果你想使用枢轴

  Select * from table 
  Pivot
    (max(case when sex='f' then value 
     end) 
      ) for option in ('option1',
    'option2'))
   Pivot
    (max(case when sex='m' then value 
     end) 
      ) for option in ('option1',
    'option2'))

【讨论】:

【参考方案3】:

PIVOT 子句一次可以处理多个数据透视列:

create table t(age,sex,val,opt ) as            
select 1, 'f', 0.019500000000000000, 'OPTION_1' from dual union all
select 2, 'f', 0.019500000000000000, 'OPTION_1' from dual union all
select 3, 'f', 0.019500000000000000, 'OPTION_1' from dual union all
select 4, 'f', 0.019500000000000000, 'OPTION_1' from dual union all
select 5, 'f', 0.019500000000000000, 'OPTION_1' from dual union all
select 1, 'm', 0.081000000000000002, 'OPTION_1' from dual union all
select 2, 'm', 0.081000000000000002, 'OPTION_1' from dual union all
select 3, 'm', 0.081000000000000002, 'OPTION_1' from dual union all
select 4, 'm', 0.081000000000000002, 'OPTION_1' from dual union all
select 5, 'm', 0.081000000000000002, 'OPTION_1' from dual union all
select 1, 'f', 0.159000000000000002, 'OPTION_2' from dual union all
select 2, 'f', 0.107999999999999999, 'OPTION_2' from dual union all
select 3, 'f', 0.073500000000000009, 'OPTION_2' from dual union all
select 4, 'f', 0.063000000000000000, 'OPTION_2' from dual union all
select 5, 'f', 0.059999999999999997, 'OPTION_2' from dual union all
select 1, 'm', 0.307499999999999996, 'OPTION_2' from dual union all
select 2, 'm', 0.220500000000000002, 'OPTION_2' from dual union all
select 3, 'm', 0.156000000000000000, 'OPTION_2' from dual union all
select 4, 'm', 0.133500000000000008, 'OPTION_2' from dual union all
select 5, 'm', 0.115500000000000005, 'OPTION_2' from dual;

select * from t
pivot(max(val) for (sex, opt) in (
  ('f','OPTION_1') as f_1,
  ('m','OPTION_1') as m_1,
  ('f','OPTION_2') as f_2,
  ('m','OPTION_2') as m_2
));

AGE F_1     M_1                   F_2                   M_2
1   0,0195  0,081000000000000002  0,159000000000000002  0,307499999999999996
2   0,0195  0,081000000000000002  0,107999999999999999  0,220500000000000002
4   0,0195  0,081000000000000002  0,063                 0,133500000000000008
5   0,0195  0,081000000000000002  0,059999999999999997  0,115500000000000005
3   0,0195  0,081000000000000002  0,073500000000000009  0,156

【讨论】:

以上是关于Oracle Pivot 多列的主要内容,如果未能解决你的问题,请参考以下文章

使用 PIVOT 函数的行到列 (Oracle)

Hive 行转列 & 列转行

ORACLE:动态数据的 PIVOT 表

ORACLE 上的 PIVOT / GROUP BY 问题

oracle pivot 和 unpivot 函数的使用

Oracle pivot & unpivot