Oracle SQL объединение таблицы 1 с таблицей 2 с нулевым результатом, если таблица 2 содержит больше - PullRequest
1 голос
/ 09 июля 2020

Я попытаюсь объяснить на примере.

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

table1
column1 column2 column3
000001   ABC     COD1
000001   ABC     COD2
000002   BCD     COD3
000003   EDF     COD1
000003   EDF     COD3
000004   FGH     COD1
000004   FGH     COD2
000004   FGH     COD3
000004   FGH     COD4

table2
column3
COD1
COD2
COD3
COD4
COD5
COD6
COD7

table2 содержит только весь возможный код column3 table1 (и только это). table1 содержит мои реальные данные. Мне не нужны table2 COD5 COD6 и COD7

Мне нужно получить такой результат

000001   ABC     COD1
000001   ABC     COD2
null     null    COD3
null     null    COD4
null     null    COD1
null     null    COD2
000002   BCD     COD3
null     null    COD4
000003   EDF     COD1
null     null    COD2
000003   EDF     COD3
null     null    COD4
000004   FGH     COD1
000004   FGH     COD2
000004   FGH     COD3
000004   FGH     COD4

Мне нужно сделать это с помощью oracle SQL, но я не уверен, возможно ли это. Я могу согласиться с тем, что первый столбец всегда является моим текущим столбцом 1 (даже если столбец 2 имеет значение NULL), если необходимо. Я не хочу дублировать, например, два 000004 FGH COD4, но я хочу дублировать, если ноль.

Я пробовал все, что знаю ... но лучшее, что я смог сделать, - это объединение с минусом или правое соединение в подзапросе, где мне нужно указать условие column1.

ИЗМЕНИТЬ, это правильный ответ, найденный другом, когда я пытался

select * from
(select distinct a.col1, a.col2
from table1 a
right join (select col3 from table2 f
 where f.col3 IN ('COD1','COD3','COD6')) b
on a.col3 = b.col3),
(select col3 from table2 f
 where f.col3 IN ('COD1','COD3','COD6'));

Ответы [ 4 ]

1 голос
/ 09 июля 2020

Вы ищете внешнее соединение раздела «новую» функцию, появившуюся в 2004 году, но до сих пор не широко используемую.

Ожидается, что table1 содержит для всех значений column3 по крайней мере одно значение, но column2 является разреженным и должно быть заполнено. (обратите внимание, что вам даже не нужен table2)

Запрос прост, только если вы ожидаете, что column2 будет NULL в случае его добавления, вы должны сбросить его с помощью case оператор:

select 
  tab.column1, 
  case when tab.column1 is NOT NULL then tab.column2 end column2, 
  c3.column3
from tab
partition by (column2)
right outer join 
(select distinct column3 from tab) c3
on tab.column3 = c3.column3
order by tab.column2, c3.column3;

Это создает данные в соответствии с запросом:

COLUMN COL COLU
------ --- ----
000001 ABC COD1
000001 ABC COD2
           COD3
           COD4
           COD1
           COD2
000002 BCD COD3
           COD4
000003 EDF COD1
           COD2
000003 EDF COD3
           COD4
000004 FGH COD1
000004 FGH COD2
000004 FGH COD3
000004 FGH COD4

Обратите внимание, что ручное решение (т.е. перед секционированным внешним соединением ) должно получить все комбинации столбцов 2 и 3 из table1 - см. подзапрос comb ниже.

На втором шаге просто outer join comb в вашу таблицу

with col2 as(
select distinct column2 from tab),
col3 as (
select distinct column3 from tab),
comb as (
select *
from col2 cross join col3)
select tab.column1, tab.column2, comb.column3 from comb
left outer join tab 
on comb.column2 = tab.column2 and comb.column3 = tab.column3
order by comb.column2, comb.column3
;

Это дает тот же результат.

1 голос
/ 09 июля 2020

Вам необходимо использовать cross join и left join следующим образом:

SQL> with table1 (col1,col2,col3) as
  2  (select '000001','ABC','COD1' from dual union all
  3  select '000001','ABC','COD2' from dual union all
  4  select '000002','BCD','COD3' from dual union all
  5  select '000003','EDF','COD1' from dual union all
  6  select '000003','EDF','COD3' from dual ),
  7  TABLE2 (COL3) AS
  8  (SELECT 'COD1' FROM DUAL UNION ALL
  9  SELECT 'COD2' FROM DUAL UNION ALL
 10  SELECT 'COD3' FROM DUAL UNION ALL
 11  SELECT 'COD4' FROM DUAL UNION ALL
 12  SELECT 'COD5' FROM DUAL)
 13  select t11.col1, T11.COL2, T2.COL3
 14  from (SELECT DISTINCT COL1 FROM TABLE1) T1
 15  CROSS JOIN (SELECT * FROM TABLE2 WHERE COL3 IN (SELECT COL3 FROM TABLE1)) T2
 16  LEFT JOIN TABLE1 T11 ON T11.COL1 = T1.COL1 AND T2.COL3 = T11.COL3
 17  ORDER BY T1.COL1, T2.COL3;

COL1   COL COL3
------ --- ----
000001 ABC COD1
000001 ABC COD2
           COD3
           COD1
           COD2
000002 BCD COD3
000003 EDF COD1
           COD2
000003 EDF COD3

9 rows selected.

SQL>
1 голос
/ 09 июля 2020

Следующий запрос поможет

    with t2 as (
    select c3
      from t2
     where c3 in ('COD1', 'COD2', 'COD3', 'COD4')
    )
   ,t3 as (
    select distinct
           c1
          ,c2
      from t1
   )    
  ,t_all as (
   select t3.c1
         ,t3.c2
         ,t2.c3
     from t3
         ,t2 
   )
   select t1.c1
         ,t1.c2
         ,t_all.c3
     from t_all left join t1 on 
          t1.c1 = t_all.c1 and t1.c2 = t_all.c2 and t1.c3 = t_all.c3
1 голос
/ 09 июля 2020

Вы можете использовать cross join для генерации строк, а затем left join:

select t1.col1, t1.col2, c3.col3
from (select distinct col1 from table1) c1 cross join
     table2 c3 left join
     table1 t1
     on t1.col1 = c1.col1 and t1.col3 = c3.col3
order by c1.col1, c3.col3;

Примечание. Кажется странным, что у вас есть значения NULL в первых двух столбцах. Это приводит к точному дублированию строк. Если вы используете select c1.col1, t1.col2, c3.col3, у вас будут допустимые значения в первом столбце.

...