#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
Ответ №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 или подзапросе точно так же, как любой другой результирующий набор.