Разбить таблицу пополам по столбцам и расположить ее в указанном ниже порядке

#sql #oracle

#sql #Oracle

Вопрос:

У меня есть таблица, подобная этой :

cat1 Цена PriceB тип1 cat2 костА costB тип2
Великобритания 55 70 X МОЖНО 25 15 Z
Великобритания 30 26 Y IND 20 20 Z
Новая Зеландия 38 36 Z GER 40 25 Y
США 47 49 Z AUS 60 15 X

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

cat3 totalA Итого Тип
Великобритания 55 70 X
Великобритания 30 26 Y
Новая Зеландия 38 36 Z
США 47 49 Z
МОЖНО 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
  

Редактировать:

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

cat1 cat2
Великобритания МОЖНО
Великобритания IND
Новая Зеландия GER
США AUS

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

cat3
Великобритания
Великобритания
Новая Зеландия
США
МОЖНО
IND
GER
AUS

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

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

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

Комментарии:

1. И почему вы не можете использовать UNION ALL, это домашнее задание?

2. @JoakimDanielson Потому что исходная таблица представляет собой внутреннее объединение нескольких таблиц, и это делает запрос огромным и громоздким и, вероятно, также повлияет на производительность, если мы удвоим количество внутренних соединений

3. почему голосование «против»?

4. Я бы предположил, что отрицательный результат вызван тем, что ваш вопрос трудно понять. В комментарии вы сказали «Потому что исходная таблица является внутренним соединением нескольких таблиц » . Итак, ваша «исходная таблица» на самом деле является запросом? Вы должны опубликовать вопрос, который точно отражает проблему, которую вы пытаетесь решить. В противном случае люди подумают, что вы пытаетесь решить тривиальную проблему, и проголосуют против, или потратят свое время на публикацию предложения, которое вам не поможет.

Ответ №1:

Вы можете начать с 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
  

Demo

Ответ №2:

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

 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, если оптимизатор сочтет, что это наилучший подход, устраняя ваши проблемы с производительностью.

Комментарии:

1. В первом методе я помещаю запрос, который выдает результат в виде таблицы, вместо t, например: select (случай, когда n.n = 1, тогда t.cat1, иначе t.cat2 end) как cat, ….from (выберите …..) t перекрестное соединение (выберите …..) n; Но это выдает ошибку: отсутствует выражение

2. @katipra . . . «2» как отсутствующий.

3. Спасибо, но я не могу выполнить дальнейший выбор и группировку по результирующему выводу.

4. @katipra . . . Я понятия не имею, что должен означать этот комментарий. Результатом является результирующий набор; вы можете использовать его в представлении, CTE или подзапросе точно так же, как любой другой результирующий набор.