Разбейте таблицу пополам по столбцам и разместите в указанном ниже порядке - PullRequest
0 голосов
/ 10 марта 2019

У меня есть такая таблица:

+------+--------+--------+------+------+-------+-------+------+
| cat1 | priceA | priceB | type1| cat2 | costA | costB | type2|
+------+--------+--------+------+------+-------+-------+------+
| UK   | 55     | 70     | X    | CAN  | 25    | 15    | Z    |
| UK   | 30     | 26     | Y    | IND  | 20    | 20    | Z    |
| NZ   | 38     | 36     | Z    | GER  | 40    | 25    | Y    |
| USA  | 47     | 49     | Z    | AUS  | 60    | 15    | X    |
+------+--------+--------+------+------+-------+-------+------+

Мне нужно получить его, как показано ниже, без использования UNION или UNION ALL

+------+--------+--------+------+
| cat3 | totalA | totalB | type |
+------+--------+--------+------+
| UK   | 55     | 70     | X    |
| UK   | 30     | 26     | Y    |
| NZ   | 38     | 36     | Z    |
| USA  | 47     | 49     | Z    |
| CAN  | 25     | 15     | Z    |
| IND  | 20     | 20     | Z    |
| GER  | 40     | 25     | Y    |
| AUS  | 60     | 15     | X    |
+------+--------+--------+------+

У меня нет разрешения на создание процедур, поэтому нет PL/SQL. Любые способы сделать это без использования следующего в Oracle?

select cat1, priceA, priceB, type1
UNION ALL
select cat2,costA,costB,type2

EDIT:

для таблицы с двумя столбцами, например:

+------+------+
| cat1 | cat2 |
+------+------+
| UK   | CAN  |
| UK   | IND  |
| NZ   | GER  |
| USA  | AUS  |
+------+------+

Чтобы получить это:

+------+
| cat3 |
+------+
| UK   |
| UK   |
| NZ   |
| USA  |
| CAN  |
| IND  |
| GER  |
| AUS  |
+------+

Я могу использовать это:

SELECT 
   cat3 
FROM 
(
    SELECT cat1, cat2 AS cat3
    WHERE <conditions>
) T UNPIVOT (cat3 FOR COL IN (cat1, cat2))

Но как это сделать для нескольких столбцов?

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

Эффективный способ отменить это:

select (case when n.n = 1 then cat1 else cat2 end) as cat,
       (case when n.n = 1 then priceA else costA end) as totalB,
       (case when n.n = 1 then priceB else costB end) as totalB,
       (case when n.n = 1 then type1 else typ2 end) as type
from t cross join
     (select 1 as n from dual union all select 2 from dual) n;

Не знаю, нарушает ли это довольно странное ограничение на union all. Но это также можно сформулировать как:

from t cross join
     (select rownum as n from t where rownum <= 2) n;

В Oracle 12C боковое соединение - это путь (хотя для этого все еще требуется union all:

select v.*
from t cross apply
     (select t.cat1 as cat3, t.priceA as totalA, t.priceB as totalB, t.type1 as type union all
      select t.cat2, t.costA, t.costB, t.type2
     ) v;

И, наконец, union all будет хорошо с CTE:

with cte as (
      . . .
     )
select t.cat1 as cat3, t.priceA as totalA, t.priceB as totalB, t.type1 as type
from cte t
union all
select t.cat2, t.costA, t.costB, t.type2
from cte t;

Oracle материализует CTE, если оптимизатор выберет лучший подход, устраняя ваши проблемы с производительностью.

0 голосов
/ 10 марта 2019

Вы можете начать с cross join и закончить case..when инструкциями, как показано ниже:

with tab( cat1 , priceA , priceB , type1 , 
          cat2 , costA  , costB  , type2 ) as
(
 select 'UK' , 55, 70 , 'X' , 'CAN' , 25 , 15 , 'Z' from dual union all    
 select 'UK' , 30, 26 , 'Y' , 'IND' , 20 , 20 , 'Z' from dual union all    
 select 'NZ' , 38, 36 , 'Z' , 'GER' , 40 , 25 , 'Y' from dual union all    
 select 'USA', 47, 49 , 'Z' , 'AUS' , 60 , 15 , 'X' from dual
), tab2 as
(
select t1.cat1 , t1.priceA , t1.priceB , t1.type1,
       t2.cat2 , t2.costA  , t2.costB  , t2.type2, 
       row_number() over ( partition by t1.cat1, t1.type1 order by t1.cat1, t1.type1 ) rn
  from tab t1
  cross join tab t2
), tab3 as
(
select t.*, mod(rn,2) as r2
  from tab2 t
) 
select distinct
       ( case when r2 = 1 then cat1 else cat2 end ) as cat1,
       ( case when r2 = 1 then priceA else costA end ) as priceA,
       ( case when r2 = 1 then priceB else costB end ) as priceB,
       ( case when r2 = 1 then type1 else type2 end ) as type1
  from tab3;

CAT1 PRICEA PRICEB  TYPE1
AUS  60     15      X
UK   55     70      X
NZ   38     36      Z
UK   30     26      Y
USA  47     49      Z
IND  20     20      Z
CAN  25     15      Z
GER  40     25      Y

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...