transpose column to row oracle

不问归期 提交于 2019-11-30 20:41:51

问题


I have a query returned value in this form (query return more than 50 columns).

 1-99transval  100-200transval  200-300transval ... 1-99nontransval 100...
   50              90                 80                  67           58

For a row value. I want these details to be converted into columns and take the following shape:

Range       Transval      NonTransval
1-99        50            67
100-200     90            58

回答1:


In pure SQL, it will need a lot of coding because you will have to manually put the range as there is no relation between the values and the range at all. Had there been a relationship, you could use CASE expression and build the range dynamically.

SQL> WITH DATA AS
  2    (SELECT 50 "1-99transval",
  3      90 "100-200transval",
  4      80 "200-300transval",
  5      67 "1-99nontransval",
  6      58 "100-200nontransval",
  7      88 "200-300nontransval"
  8    FROM dual
  9    )
 10  SELECT '1-99' range,
 11    "1-99transval" transval,
 12    "1-99nontransval" nontransval
 13  FROM DATA
 14  UNION
 15  SELECT '100-200' range,
 16    "100-200transval",
 17    "100-200nontransval" nontransval
 18  FROM DATA
 19  UNION
 20  SELECT '200-300' range,
 21    "200-300transval",
 22    "200-300nontransval" nontransval
 23  FROM DATA;

RANGE     TRANSVAL NONTRANSVAL
------- ---------- -----------
1-99            50          67
100-200         90          58
200-300         80          88

From Oracle database 11g Release 1 and above, you could use UNPIVOT

SQL> WITH DATA AS
  2    (SELECT 50 "1-99transval",
  3      90 "100-200transval",
  4      80 "200-300transval",
  5      67 "1-99nontransval",
  6      58 "100-200nontransval",
  7      88 "200-300nontransval"
  8    FROM dual
  9    )
 10  SELECT *
 11  FROM   DATA
 12  UNPIVOT( (transval,nontransval)
 13  FOR RANGE IN ( ("1-99transval","1-99nontransval") AS '1-99'
 14                ,("100-200transval","100-200nontransval") AS '100-200'
 15                ,("200-300transval","200-300nontransval") AS '200-300'));

RANGE     TRANSVAL NONTRANSVAL
------- ---------- -----------
1-99            50          67
100-200         90          58
200-300         80          88

Above, in your case you need to replace the WITH clause with your existing query as a sub-query. You need to include other columns in the UNION.

In PL/SQL, you could (ab)use EXECUTE IMMEDIATE and get the "range" by extracting the column names in dynamic sql.

Although, it would be much better to modify/rewrite your existing query which you have not shown yet.




回答2:


If you are using Oracle 11g version then you can use the UNPIVOT feature.

CREATE TABLE DATA AS
SELECT 50 "1-99transval",
    90 "100-200transval",
    80 "200-300transval",
    67 "1-99nontransval",
    58 "100-200nontransval",
    88 "200-300nontransval"
  FROM dual


SELECT *
FROM   DATA
UNPIVOT( (Transval,NonTransval) FOR Range IN ( ("1-99transval","1-99nontransval") as '1-99'
                                            ,("100-200transval","100-200nontransval") as '100-200'
                                            ,("200-300transval","200-300nontransval") as '200-300'))

http://sqlfiddle.com/#!4/c9747/3/0



来源:https://stackoverflow.com/questions/33206907/transpose-column-to-row-oracle

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!