重新排列 table 将值转换为列名

Rearranging a table converting values to column names

作为 XML 实现动态数据输入工具的结果,我得到了以下 table

TRGID   C_NAME     I_ID COLUMNID    TARGET_DESC     DEPT_NAME   VALUE

20158   Outlook     2   1000        Production      Operations  2.501
20158   Outlook     4   1000        Production      Operations  1.5
20158   Outlook     3   1000        Production      Operations  0.2
20158   Outlook     1   1000        Production      Operations  1.9
20158   Target      1   2111        Production      Operations  2.1
20158   Target      4   2111        Production      Operations  1.2
20158   Target      2   2111        Production      Operations  11.2
20158   Target      3   2111        Production      Operations  1.58
20158   Month       4   3222        Production      Operations  1-May-2010
20158   Month       3   3222        Production      Operations  1-Apr-2010
20158   Month       2   3222        Production      Operations  1-Jan-2015
20158   Month       1   3222        Production      Operations  1-Mar-2015
20158   Actual      4   4333        Production      Operations  2.5
20158   Actual      3   4333        Production      Operations  3.5
20158   Actual      2   4333        Production      Operations  10.8
20158   Actual      1   4333        Production      Operations  2
20163   Month       2   1000        Maintenance     Operations  1-Feb-2015
20163   Month       1   1000        Maintenance     Operations  1-Jan-2010
20163   Outlook     2   2111        Maintenance     Operations  18.56
20163   Outlook     1   2111        Maintenance     Operations  2.3
20163   Actual      2   3222        Maintenance     Operations  28.2
20163   Actual      1   3222        Maintenance     Operations  1.4
20163   Goal        2   4333        Maintenance     Operations  3.98
20163   Goal        1   4333        Maintenance     Operations  3.6

我希望结果如下

TRGID   I_ID      Month      Actual  Outlook    Target      Goal
20158    1      1-Mar-2015     2       1.9        2.1   
20158    2      1-Jan-2015     10.8    2.501      11.2  
20158    3      1-Apr-2010     3.5     0.2        1.58  
20158    4      1-May-2010     2.5     1.5        1.2   
20163    1      1-Jan-2010     1.4     2.3                  3.6
20163    2      1-Feb-2015     28.2    18.56                3.98

我想要一个能够适应数据变化而不仅仅是当前数据的解决方案。

我正在使用 Oracle 10g

如果您有 Oracle 11g,请使用 Pivot

WITH table_(TRGID, C_NAME, I_ID, COLUMNID, TARGET_DESC, DEPT_NAME, VALUE) AS 
(
    select 20158, 'Outlook', 2, 1000, 'Production', 'Operations', '2.501' from dual union all
    select 20158, 'Outlook', 4, 1000, 'Production', 'Operations', '1.5' from dual union all
    select 20158, 'Outlook', 3, 1000, 'Production', 'Operations', '0.2' from dual union all
    select 20158, 'Outlook', 1, 1000, 'Production', 'Operations', '1.9' from dual union all
    select 20158, 'Target', 1, 2111, 'Production', 'Operations', '2.1' from dual union all
    select 20158, 'Target', 4, 2111, 'Production', 'Operations', '1.2' from dual union all
    select 20158, 'Target', 2, 2111, 'Production', 'Operations', '11.2' from dual union all
    select 20158, 'Target', 3, 2111, 'Production', 'Operations', '1.58' from dual union all
    select 20158, 'Month', 4, 3222, 'Production', 'Operations', '1-May-2010' from dual union all
    select 20158, 'Month', 3, 3222, 'Production', 'Operations', '1-Apr-2010' from dual union all
    select 20158, 'Month', 2, 3222, 'Production', 'Operations', '1-Jan-2015' from dual union all
    select 20158, 'Month', 1, 3222, 'Production', 'Operations', '1-Mar-2015' from dual union all
    select 20158, 'Actual', 4, 4333, 'Production', 'Operations', '2.5' from dual union all
    select 20158, 'Actual', 3, 4333, 'Production', 'Operations', '3.5' from dual union all
    select 20158, 'Actual', 2, 4333, 'Production', 'Operations', '10.8' from dual union all
    select 20158, 'Actual', 1, 4333, 'Production', 'Operations', '2' from dual union all
    select 20163, 'Month', 2, 1000, 'Maintenance', 'Operations', '1-Feb-2015' from dual union all
    select 20163, 'Month', 1, 1000, 'Maintenance', 'Operations', '1-Jan-2010' from dual union all
    select 20163, 'Outlook', 2, 2111, 'Maintenance', 'Operations', '18.56' from dual union all
    select 20163, 'Outlook', 1, 2111, 'Maintenance', 'Operations', '2.3' from dual union all
    select 20163, 'Actual', 2, 3222, 'Maintenance', 'Operations', '28.2' from dual union all
    select 20163, 'Actual', 1, 3222, 'Maintenance', 'Operations', '1.4' from dual union all
    select 20163, 'Goal', 2, 4333, 'Maintenance', 'Operations', '3.98' from dual union all
    select 20163, 'Goal', 1, 4333, 'Maintenance', 'Operations', '3.6' from dual)
-- End if data Preparation
    SELECT *
      FROM (SELECT trgid,
                   c_name,
                   i_id,
                   VALUE
              FROM table_) pivot(MIN(VALUE) FOR c_name IN('Month' AS MONTH,
                                                          'Actual' AS actual,
                                                          'Outlook' as outlook,
                                                          'Target' AS target,
                                                          'Goal' AS goal))

输出

| TRGID | I_ID |      MONTH | ACTUAL | OUTLOOK | TARGET |   GOAL |
|-------|------|------------|--------|---------|--------|--------|
| 20158 |    2 | 1-Jan-2015 |   10.8 |   2.501 |   11.2 | (null) |
| 20163 |    1 | 1-Jan-2010 |    1.4 |     2.3 | (null) |    3.6 |
| 20163 |    2 | 1-Feb-2015 |   28.2 |   18.56 | (null) |   3.98 |
| 20158 |    1 | 1-Mar-2015 |      2 |     1.9 |    2.1 | (null) |
| 20158 |    4 | 1-May-2010 |    2.5 |     1.5 |    1.2 | (null) |
| 20158 |    3 | 1-Apr-2010 |    3.5 |     0.2 |   1.58 | (null) |

对于 < 11 g 的版本,使用下面的查询,

SELECT trgid,
       i_id,
       MIN(CASE c_name WHEN 'Month' THEN VALUE ELSE NULL END) AS MONTH,
       MIN(CASE c_name WHEN 'Actual' THEN VALUE ELSE NULL END) AS actual,
       MIN(CASE c_name WHEN 'Outlook' THEN VALUE ELSE NULL END) AS outlook,
       MIN(CASE c_name WHEN 'Target' THEN VALUE ELSE NULL END) AS target,
       MIN(CASE c_name WHEN 'Goal' THEN VALUE ELSE NULL END) AS goal
  FROM table_
 GROUP BY trgid, i_id;