Создание дубликатов с использованием объединения с фильтром

#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
  

Demo

Ответ №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 |
 ------------- ----------- -------------- ----- -----