【问题标题】:Transpose a query output转置查询输出
【发布时间】:2013-09-16 10:58:07
【问题描述】:

我有一个正常的选择查询,结果如下输出。

select cid,x1,x2,x3,x4,fy
  from temp_table;

cid     x1  x2  x3  x4  fy
----------------------------
6657    100 0   0   200 2014
6658    300 0   0   400 2015
6659    500 0   0   600 2016

我希望它重写它打印以下输出。

    2014    2015    2016    
-------------------------   
x1  100     300     500     
x2  0       0       0       
x3  0       0       0       
x4  200     400     600 

如何做到这一点?

【问题讨论】:

    标签: sql oracle11g transpose


    【解决方案1】:

    这是一种只使用子查询和聚合的方法:

    select name,
           sum(case when fy = 2014 then x end) as "2014",
           sum(case when fy = 2015 then x end) as "2015",
           sum(case when fy = 2016 then x end) as "2016"
    from (select fy,
                 (case when n.n = 1 then 'x1'
                       when n.n = 2 then 'x2'
                       when n.n = 3 then 'x3'
                       when n.n = 4 then 'x4'
                  end) as name,
                 (case when n.n = 1 then x1
                       when n.n = 2 then x2
                       when n.n = 3 then x3
                       when n.n = 4 then x4
                  end) as x
          from temp_table cross join
                (select 1 as n from dual union all
                 select 2 from dual union all
                 select 3 from dual union all
                 select 4 from dual
                ) n
         ) t
    group by name;
    

    您也可以使用pivot,但这是最近才添加到 Oracle SQL 中的,所以我倾向于使用这种方法。

    【讨论】:

    • 知道如何使用pivot 来做这件事我正在使用oracle 11g。可能存在我们的查询输出中有 n 年的情况,因此转置查询应该有 n+1 列
    【解决方案2】:

    更通用的解决方案是UNPIVOT and PIVOT
    您的 temp_table 已经是一个以 (x1 x2 x3 x4) 作为 x-axisfy 作为 y-axis 的数据透视表
    首先我们需要将temp_table UNPIVOT 到unpivoted_temp_table,然后以 fy 作为 x 轴和 (x1 x2 x3 x4) 作为 y 轴进行 PIVOT: p>

    with unpivoted_temp_table as (
    
    SELECT *
      FROM   temp_table
      UNPIVOT (
              totalSales                            
              FOR x                             
              IN  (x1, x2, x3, x4)
             )
    )  
    
    select *  
    FROM   unpivoted_temp_table 
      PIVOT (
                   SUM(totalSales)        
               FOR fy          
              IN (2014, 2015, 2016)
             )
    order by 1 --order by column X
    

    http://sqlfiddle.com/#!4/4fdfc/1/0

    【讨论】:

      【解决方案3】:

      在 Oracle 11G 中转置的三个可能选项

      • 解码选项

        • 一个。如果要转置,请对新列使用 SUM 和 DECODE 并总结

        • b.如果要转置,请对新列使用 MAX 和 DECODE 而不是总结

      • 使用 PIVOT

      • 如 Gordon 所说,使用 WITH 和 SUB SELECT

      要使用数据透视,在您的代码中是不可能的,因为您的初始数据集已经被透视。

      WITH TEMP1
          AS (SELECT
                   6657 AS CID,
                   100 AS VAL,
                   'X1' AS XCORD,
                   2014 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6657 AS CID,
                   0 AS VAL,
                   'X2' AS XCORD,
                   2014 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6657 AS CID,
                   0 AS VAL,
                   'X3' AS XCORD,
                   2014 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6657 AS CID,
                   200 AS VAL,
                   'X4' AS XCORD,
                   2014 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6658 AS CID,
                   300 AS VAL,
                   'X1' AS XCORD,
                   2015 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6658 AS CID,
                   0 AS VAL,
                   'X2' AS XCORD,
                   2015 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6658 AS CID,
                   0 AS VAL,
                   'X3' AS XCORD,
                   2015 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6658 AS CID,
                   400 AS VAL,
                   'X4' AS XCORD,
                   2015 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6659 AS CID,
                   500 AS VAL,
                   'X1' AS XCORD,
                   2016 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6659 AS CID,
                   0 AS VAL,
                   'X2' AS XCORD,
                   2016 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6659 AS CID,
                   0 AS VAL,
                   'X3' AS XCORD,
                   2016 AS FY
              FROM
                   DUAL
              UNION ALL
              SELECT
                   6659 AS CID,
                   600 AS VAL,
                   'X4' AS XCORD,
                   2016 AS FY
              FROM
                   DUAL)
      SELECT
            *
      FROM
            (SELECT
                  XCORD,
                  FY,
                  SUM ( VAL ) AS VAL
             FROM
                  TEMP1
             GROUP BY
                  XCORD,
                  FY) PIVOT (SUM ( VAL ) FOR FY IN ('2014', '2015', '2016'))
      ORDER BY
            XCORD;
      

      结果:

      XCORD   '2014'  '2015'  '2016'
      -----   ------  ------  ------
      X1  100 300 500
      X2  0   0   0
      X3  0   0   0
      X4  200 400 600
      

      如果你查看数据集,你可以看到结果是

      CID     VAL     XCORD   FY
      ----    ----    -----   ----
      6657    100 X1  2014
      6657    0   X2  2014
      6657    0   X3  2014
      6657    200 X4  2014
      6658    300 X1  2015
      6658    0   X2  2015
      6658    0   X3  2015
      6658    400 X4  2015
      6659    500 X1  2016
      6659    0   X2  2016
      6659    0   X3  2016
      6659    600 X4  2016
      

      这或多或少是您数据的 UNPIVOT。

      【讨论】:

        【解决方案4】:

        您可以结合使用 unpivot 和 pivot 来做到这一点。

        select * from 
            (select * from 
            (select x1,x2,x3,x4,fy from table1) 
            unpivot(val for x in (x1,x2,x3,x4)))
        pivot(sum(val) for fy in (2014,2015,2016))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-09
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          相关资源
          最近更新 更多