2015-09-15 5 views
1

У меня есть эта строка в моей таблице mtinre:Условные транспонирования столбцов в строки в Oracle SQL

INREPRCO INRESELO INRECAPI INRECFRA INRECAPO 
---------- ---------- ---------- ---------- ---------- 
    32.42  1.87   1      5 

я построить запрос, чтобы перенести эту строку, как 5 различных строк для каждого столбца.

SELECT CASE pivot 
      WHEN 1 THEN 'VAPRS' 
      WHEN 2 THEN 'VAFRC' 
      WHEN 3 THEN 'VACTA' 
      WHEN 4 THEN 'VIMSL' 
      WHEN 5 THEN 'VINEM' 
     END 
      component, 
     CASE pivot 
      WHEN 1 THEN inreprco 
      WHEN 2 THEN inrecfra 
      WHEN 3 THEN inrecapo 
      WHEN 4 THEN inreselo 
      WHEN 5 THEN inreinem 
      ELSE NULL 
     END 
      VALUE, 
     CASE pivot 
      WHEN 4 
      THEN 
      (NVL (inreprco, 0) + NVL (inrecfra, 0) + NVL (inrecapo, 0)) 
      WHEN 5 
      THEN 
      (NVL (inreprco, 0) + NVL (inrecfra, 0) + NVL (inrecapo, 0)) 
      ELSE 
      NULL 
     END 
      AS base 
    FROM mtinre, 
     ( SELECT ROWNUM pivot 
       FROM DUAL 
     CONNECT BY LEVEL <= 5) 

Выход:

COMPONENT  VALUE  BASE 
--------- ---------- ---------- 
VAPRS   32.42   
VAFRC       
VACTA    5   
VIMSL   1.87  37.42 
VINEM   .94  37.42 

Но эти 5 полей (INREPRCO, INRESELO, INRECAPI, INRECFRA, INRECAPO) может иметь нуль или нулевые значения (0). Поэтому мне нужно выбрать только те, которые имеют значения. В последнем примере, только покажите мне:

COMPONENT  VALUE  BASE 
--------- ---------- ---------- 
VAPRS   32.42   
VACTA    5   
VIMSL   1.87  37.42 
VINEM   .94  37.42 

Я пытался поставить некоторые, где условия, но подключения постановкой уровня создает мне всегда 5 строк.

Итак, я изменил свой запрос и сделал это:

SELECT * 
    FROM (SELECT CASE pivot 
        WHEN 1 THEN 'VAPRS' 
        WHEN 2 THEN 'VAFRC' 
        WHEN 3 THEN 'VACTA' 
        WHEN 4 THEN 'VIMSL' 
        WHEN 5 THEN 'VINEM' 
       END 
        component, 
       CASE pivot 
        WHEN 1 THEN inreprco 
        WHEN 2 THEN inrecfra 
        WHEN 3 THEN inrecapo 
        WHEN 4 THEN inreselo 
        WHEN 5 THEN inreinem 
        ELSE NULL 
       END 
        VALUE, 
       CASE pivot 
        WHEN 4 
        THEN 
        ( NVL (inreprco, 0) 
         + NVL (inrecfra, 0) 
         + NVL (inrecapo, 0)) 
        WHEN 5 
        THEN 
        ( NVL (inreprco, 0) 
         + NVL (inrecfra, 0) 
         + NVL (inrecapo, 0)) 
        ELSE 
        NULL 
       END 
        AS base 
      FROM mtinre, 
       ( SELECT ROWNUM pivot 
         FROM DUAL 
       CONNECT BY LEVEL <= 5)) 
WHERE VALUE IS NOT NULL 

Он работает, но есть ли другой способ сделать это без использования суб оператор выбора? Любое предложение?

Благодаря Филипе

ответ

3

Использование UNPIVOT и небольшой трюк может сделать эту работу. Почти во всех таблицах есть столбец id (первичный или уникальный ключ). Предполагая, что таблица имеет id_col в качестве столбца идентификаторов, этот запрос будет выполнять работу

SQL> WITH table_(id_col, inreprco,inreselo,inrecapi,inrecfra,inrecapo) AS 
    2 (SELECT 1, 32.42,1.87,0.94,NULL,5 FROM dual UNION ALL 
    3 SELECT 2, 33.43,2.87,0.87,12,9 FROM dual), 
    4 --------- 
    5 -- End of data preparation 
    6 --------- 
    7 table2_ AS (SELECT id_col, component, VALUE 
    8    FROM table_ 
    9   UNPIVOT (VALUE FOR component IN (inreprco AS 'VAPRS', inrecfra AS 'VAFRC', inrecapo AS 'VACTA', inreselo AS 'VIMSL', inrecapi AS 'VINEM'))) 
10 select a.id_col, 
11   a.COMPONENT, 
12   a.VALUE, 
13   CASE WHEN a.component IN ('VIMSL', 'VINEM') THEN nvl(b.inreprco, 0) + nvl(b.inrecfra, 0) + NVL(b.inrecapo, 0) ELSE NULL END AS base 
14 FROM table2_ a 
15 INNER JOIN table_ b 
16  ON b.id_col = a.id_col; 

    ID_COL COMPONENT  VALUE  BASE 
---------- --------- ---------- ---------- 
     1 VAPRS   32.42 
     1 VACTA    5 
     1 VIMSL   1.87  37.42 
     1 VINEM   0.94  37.42 
     2 VAPRS   33.43 
     2 VAFRC    12 
     2 VACTA    9 
     2 VIMSL   2.87  54.43 
     2 VINEM   0.87  54.43 

9 rows selected 

Но если нет столбца Id, то изменяющего объединение в перекрестном соединении будет делать, но это будет возвращать правильный результат, если есть только одна строка в таблице.

SQL> WITH table_(inreprco,inreselo,inrecapi,inrecfra,inrecapo) AS 
     2 (SELECT 32.42,1.87,0.94,NULL,5 FROM dual), 
     3 --------- 
     4 -- End of data preparation 
     5 --------- 
     6 table2_ AS (SELECT component, VALUE 
     7    FROM table_ 
     8   UNPIVOT (VALUE FOR component IN (inreprco AS 'VAPRS', inrecfra AS 'VAFRC', inrecapo AS 'VACTA', inreselo AS 'VIMSL', inrecapi AS 'VINEM'))) 
     9 select a.COMPONENT, 
    10   a.VALUE, 
    11   CASE WHEN a.component IN ('VIMSL', 'VINEM') THEN nvl(b.inreprco, 0) + nvl(b.inrecfra, 0) + NVL(b.inrecapo, 0) ELSE NULL END AS base 
    12 FROM table2_ a 
    13 CROSS JOIN table_ b 
    14/

    COMPONENT  VALUE  BASE 
    --------- ---------- ---------- 
    VAPRS   32.42 
    VACTA    5 
    VIMSL   1.87  37.42 
    VINEM   0.94  37.42 

Или ждать кого-то, кто приходит с какой-либо другой подход;)

+0

Превосходное решение. У вас есть одна проблема. Мне нужно удалить из вывода поля со значением 0 (0). – milheiros

+0

Используя подходящее условие 'WHERE', вы можете удалить ненужные записи. Просто дайте нам знать, в какой области вы говорите. – San

Смежные вопросы