将行转换为像pivot一样的列

时间:2014-09-09 10:40:49

标签: oracle plsql

我有一个数据:

formid  formownerid approverid
1       100         102
1       100         103
1       100         104
2       200         107
2       200         103
2       200         109
2       200         105
3       400         201
3       400         210

我想将其转换为:

formid  formownerid approverid  approverid  approverid  approverid
1       100         102         103         104         NULL
2       200         107         103         109         105
3       400         201         202         NULL        NULL

无论我在哪里看到我都看到了pivot / unpivot,但由于我们不需要聚合,因此它看起来无关。

2 个答案:

答案 0 :(得分:4)

聚合是枢轴的必要部分,但在这里应用很简单;您不希望sum,但max聚合工作正常:

select *
from (
  select t.*,
    row_number() over (partition by formid, formownerid
      order by approverid) as rn
  from t42 t
)
pivot (max(approverid) as approverid for (rn) in (1, 2, 3, 4));

    FORMID FORMOWNERID 1_APPROVERID 2_APPROVERID 3_APPROVERID 4_APPROVERID
---------- ----------- ------------ ------------ ------------ ------------
         1         100          102          103          104              
         2         200          103          105          107          109 
         3         400          201          210                           

或者您可以明确指定列名前缀以使其成为有效标识符:

pivot (max(approverid) as approverid
  for (rn) in (1 as a, 2 as b, 3 as c, 4 as d));

内部查询是在表结果中添加一个伪列rn,以便为您提供一个固定的值,因为实际的审批者ID不会事先知道。

手动方法可能会使这一点更清晰:

select formid, formownerid,
  max(case when rn = 1 then approverid end) as approverid_1,
  max(case when rn = 2 then approverid end) as approverid_2,
  max(case when rn = 3 then approverid end) as approverid_3,
  max(case when rn = 4 then approverid end) as approverid_4
from (
  select t.*,
    row_number() over (partition by formid, formownerid
      order by approverid) as rn
  from t42 t
)
group by formid, formownerid
order by formid, formownerid;

    FORMID FORMOWNERID APPROVERID_1 APPROVERID_2 APPROVERID_3 APPROVERID_4
---------- ----------- ------------ ------------ ------------ ------------
         1         100          102          103          104              
         2         200          103          105          107          109 
         3         400          201          210                           

内部查询是相同的。 case语句按上面的方式生成每个列,但如果没有max并进行分组,则会得到多行,并且有很多额外的空白:

select formid, formownerid,
  case when rn = 1 then approverid end as approverid_1,
  case when rn = 2 then approverid end as approverid_2,
  case when rn = 3 then approverid end as approverid_3,
  case when rn = 4 then approverid end as approverid_4
from (
  select t.*,
    row_number() over (partition by formid, formownerid
      order by approverid) as rn
  from t42 t
);

    FORMID FORMOWNERID APPROVERID_1 APPROVERID_2 APPROVERID_3 APPROVERID_4
---------- ----------- ------------ ------------ ------------ ------------
         1         100          102                                        
         1         100                       103                           
         1         100                                    104              
         2         200          103                                        
         2         200                       105                           
         2         200                                    107              
         2         200                                                 109 
         3         400          201                                        
         3         400                       210                           

请注意,每个formid / formownerid组合的一列中只有一个值(最多),但它们出现在不同的行中。 max抑制那些多行;并且枢轴版本在引擎盖下做了类似的事情。

SQL Fiddle显示了中间步骤和数据透视版本的手动方法。

答案 1 :(得分:-2)

一种可能的方法:

SELECT FROMID, FROMOWNERID, APPROVERID, NULL APPROVERID, NULL APPROVERID, NULL APPROVERID
FROM   yourtable
WHERE  FROMID = 100
AND    APPROVERID =  102
UNION ALL
SELECT FROMID, FROMOWNERID, NULL APPROVERID, APPROVERID APPROVERID, NULL APPROVERID, NULL APPROVERID
FROM   yourtable
WHERE  FROMID = 100
AND    APPROVERID =  103
UNION ALL
SELECT FROMID, FROMOWNERID, NULL APPROVERID, NULL APPROVERID, APPROVERID APPROVERID, NULL APPROVERID
FROM   yourtable
WHERE  FROMID = 100
AND    APPROVERID =  104
----
-------
And So On