#sql #oracle
#sql #Oracle
Вопрос:
Я хочу дублировать свои данные, но изменить одно значение в одном столбце. Например, мне нужно, чтобы мои данные выглядели следующим образом для каждого (to) и (from)..
to from vehicle size l h
FCS011 FCS416 6025 0.1 0.3
FCS011 FCS416 6020 0.1 0.3
FCS011 FCS416 6010 0.1 0.3
FCS011 FCS416 6015 0.1 0.3
Теперь для некоторых наборов (to) и (from) у меня есть данные только для тех, где размер транспортного средства равен 6010 и 6015, а для некоторых у меня есть только данные для 6025 и 6020. Мне нужно дублировать значения для данного набора, в котором отсутствуют данные для того или иного набора.
Мои данные в настоящее время выглядят следующим образом для некоторых наборов (market_to,market_from)
to from vehicle size l h
FCS010 FCS416 6025 0.1 0.3
FCS010 FCS416 6020 0.1 0.3
FCS012 FCS416 6010 0.1 0.3
FCS012 FCS416 6015 0.1 0.3
Этот набор данных должен выглядеть следующим образом:
to from vehicle size l h
FCS010 FCS416 6025 0.1 0.3
FCS010 FCS416 6020 0.1 0.3
FCS010 FCS416 6010 0.1 0.3
FCS010 FCS416 6015 0.1 0.3
FCS012 FCS416 6010 0.1 0.3
FCS012 FCS416 6015 0.1 0.3
FCS012 FCS416 6020 0.1 0.3
FCS012 FCS416 6025 0.1 0.3
Итак, я хотел выполнить объединение all, чтобы захватить другие значения, но я не уверен, как захватить логику либо одного, либо другого. Ниже приведен мой запрос о том, что я выполнил объединение для создания дополнительных строк..
create table PA_FCS_temp
as
select
MARKET_FROM ,
MARKET_TO ,
VEHICLE_CLASS,
l,
h
from PA_FCS
UNION ALL
select MARKET_FROM ,
MARKET_TO ,
decode(VEHICLE_CLASS, '6020', '6025', '6010', '6015') as VEHICLE_CLASS,
l,
h
from PA_FCS
VEHICLE_CLASS in ('6020', '6010')
ORDER BY MARKET_FROM, MARKET_TO;
Комментарии:
1. Давайте возьмем две строки с
"to" = FCS012, "from" = FCS416
. Каждая строка имеет значение дляl
и значение дляh
. Во всех ваших примерах всеl
одинаковы, и всеh
являются одинаковыми. Однако, каков желаемый результат, еслиl
(например) между двумя строками были различия ? Какое значение вам нужно «дублировать»?
Ответ №1:
Вы можете мультиплексировать записи, заканчивающиеся только на 5
( 6015
, 6025
), используя модульную логику с перекрестным соединением в виде
select * from t where mod(vehicle_size,10)=0
union all
select t1.*
from t t1 cross join t t2
where mod(t1.vehicle_size,5)=0
and mod(t1.vehicle_size,10)!=0
Ответ №2:
Один из способов представить вашу проблему не как «дублирование строк», а скорее как «заполнение разреженных данных».
У вас есть список известных размеров транспортных средств: 6010, 6015, 6020 и 6025. У вас есть наборы данных, предоставленные market_to
и market_from
, где каждый набор может содержать не все известные размеры транспортных средств. Вы хотите заполнить разреженные данные так, чтобы каждый набор содержал все известные размеры транспортного средства.
Хорошим инструментом SQL в Oracle для заполнения разреженных данных является «разделенное» внешнее соединение. Вот как это будет работать для вашего запроса:
Настройка
CREATE TABLE market_data (
market_to varchar2(6),
market_from varchar2(6),
vehicle_size number(4),
l number,
h number);
INSERT INTO market_data
SELECT 'FCS010','FCS416',6025, 0.1, 0.3 FROM DUAL UNION ALL
SELECT 'FCS010','FCS416',6020, 0.1, 0.3 FROM DUAL UNION ALL
SELECT 'FCS012','FCS416',6010, 0.1, 0.3 FROM DUAL UNION ALL
SELECT 'FCS012','FCS416',6015, 0.1, 0.3 FROM DUAL ;
COMMIT;
Разделенный запрос внешнего соединения
(примечание: если у вас есть таблица с известными размерами транспортных средств, вы можете использовать это и опустить WITH
предложение.)
with vehicle_sizes ( vehicle_size ) AS
( SELECT column_value FROM TABLE(sys.odcinumberlist(6010, 6015, 6020, 6025)) )
select md.market_from,
md.market_to,
vs.vehicle_size,
nvl(md.l, min(md.l) over ( partition by md.market_from, md.market_to )) l,
nvl(md.h, min(md.h) over ( partition by md.market_from, md.market_to )) h
from market_data md partition by (md.market_to, md.market_from)
right outer join vehicle_sizes vs on vs.vehicle_size = md.vehicle_size;
------------- ----------- -------------- ----- ----- | MARKET_FROM | MARKET_TO | VEHICLE_SIZE | L | H | ------------- ----------- -------------- ----- ----- | FCS416 | FCS010 | 6010 | 0.1 | 0.3 | | FCS416 | FCS010 | 6015 | 0.1 | 0.3 | | FCS416 | FCS010 | 6020 | 0.1 | 0.3 | | FCS416 | FCS010 | 6025 | 0.1 | 0.3 | | FCS416 | FCS012 | 6010 | 0.1 | 0.3 | | FCS416 | FCS012 | 6015 | 0.1 | 0.3 | | FCS416 | FCS012 | 6020 | 0.1 | 0.3 | | FCS416 | FCS012 | 6025 | 0.1 | 0.3 | ------------- ----------- -------------- ----- -----