데이터는 아래와 같이
CodeA 테이블과 CodeB 테이블이 있습니다.
CodeA 테이블에 CodeB테이블의 없는 Code_ID값을 추가하고 싶습니다.. 말로도 잘 풀지 못하겠..네요
결과값이 아래처럼 나와야 하는데 잘 모르겠습니다. 도움을 부탁드립니다.
---------결과값--------
| CODE_A_PK | CODE_ID | CODE_NM | 설명 |
| PK1 | C | 코드C |
CodeA : PK1 행 기준 CodeB 테이블에 CodeA 테이블 code_id 값인 A가 있음으로 C만 추가 |
| PK2 | A | 코드A |
CodeA : PK2 행 기준 CodeB 테이블에 CodeA 테이블의 code_id 값인 A,C가 없어서 A,C 추가 |
| PK2 | C | 코드C | 위와 동 |
----------- 데이터 ---------- ------
With CodeA as ( Select 'pk1' as code_a_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk2' as code_a_pk, 'B' as code_id, '코드B' as code_nm from dual ), CodeB as ( Select 'pk1' as code_b_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk2' as code_b_pk, 'C' as code_id, '코드C' as code_nm from dual ), Select * From CodeA, CodeB
뭔본 대비 결과가 틀린게 아닌지?
pk2, C 만 추가하면 되는 것 아닌가요?
최종 결과
pk1, A - 변동없음
pk2, B - 변동없음
pk2, C - 추가
아 제가 설명을 잘 못해서 죄송합니다.
CodeB에 있는 CODE_ID 에 새로운 값이 추가되면
CodeA에 CodeB에서 추가된 CODE_ID 값을 찾아서 있으면 pass, 없으면 추가, 기존 테이블에 값이 추가 되는건 아니라 새로운 표를 만드는 로직입니다..
기존에 CodeA 에 'A', 'B'만 존재하다가
CodeB 에 'A','C'가 추가 되었을 시
- CodeA 의 pk1, A는 CodeB에서 추가한 A와 겹쳐서 pass 이고 C는 없으니 추가
- CodeA 의 pk2, B는 CodeB에서 추가한 A,C 가 없어서 새로운 표에 추가..
이런 로직인데 설명도 두서없이 죄송합니다.
CodeB에 있는 CODE_ID 에 새로운 값이 추가되면
CodeA에 CodeB에서 추가된 CODE_ID 값을 찾아서 있으면 pass, 없으면 추가.
이런 로직에서 CodeB 테이블의 pk 값은 비교대상이 아닌건가요?
아마도 지금 설명하신 로직은
1. CodeB 테이블에 A, C 값이 추가됨(pk 상관 없이)
2. CodeA 테이블의 pk1 에서 A 값이 있으므로 C값이 추가
3. CodeA 테이블의 pk2 에서 A, C 값이 없으므로 둘다 추가
인듯 싶은데, 그렇다면 CodeB 테이블의 pk 값은 사용되지 않는 값인듯 합니다
With CodeA as ( Select 'pk1' as code_a_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk2' as code_a_pk, 'B' as code_id, '코드B' as code_nm from dual ), CodeB as ( Select 'pk1' as code_b_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk2' as code_b_pk, 'C' as code_id, '코드C' as code_nm from dual ) Select a.code_a_pk, b.code_id, b.code_nm From CodeA a ,CodeB b where a.code_id <> b.code_id order by 1, 2
수정본 / 위의 쿼리는 codeA 테이블의 code_a_pk 값에 대해 code_id 값이 1개만 배정될때 정상 동작 하네요....
With CodeA as ( Select 'pk1' as code_a_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk1' as code_a_pk, 'C' as code_id, '코드C' as code_nm from dual union all -- 테스트를 위한 추가행 Select 'pk2' as code_a_pk, 'B' as code_id, '코드B' as code_nm from dual ) ,CodeB as ( Select 'pk1' as code_b_pk, 'A' as code_id, '코드A' as code_nm from dual union all Select 'pk2' as code_b_pk, 'C' as code_id, '코드C' as code_nm from dual ) ,temp as ( Select a.code_a_pk, b.code_id, b.code_nm From CodeA a inner join (select distinct code_id, code_nm from CodeB) b on a.code_id = b.code_id ) select a.code_a_pk, b.code_id, b.code_nm from CodeA a left outer join (select distinct code_id, code_nm from CodeB) b on a.code_id <> b.code_id where (a.code_a_pk, b.code_id) not in (select t.code_a_pk, t.code_id from temp t) order by 1, 2
뭔가 많이 복잡해졌지만....
넵 맞습니다..
풀 조인하고 일치하지 않으면 으로도 되는 것이군용.
감사합니다.
성능상 풀조인해도 크게 문제되지 않을까요?
B에서 pk 를 따로 입력 받으면서 사용하지 않는 것이 맞는지? 의문입니다.
넵 CodeB의 pk는 무의미한 값입니다.
실제로는 없는 값.. 입니다.
WITH CodeA AS
(
SELECT 'pk1' code_a_pk, 'A' code_id, '코드A' code_nm FROM dual
UNION ALL SELECT 'pk2', 'B', '코드B' FROM dual
)
, CodeB AS
(
SELECT 'A' code_id, '코드A' code_nm FROM dual
UNION ALL SELECT 'C', '코드C' FROM dual
)
SELECT a.code_a_pk
, b.code_id
, b.code_nm
FROM CodeB b
LEFT JOIN CodeA a
PARTITION BY (a.code_a_pk)
ON b.code_id = a.code_id
WHERE a.code_id IS NULL
;
와.... 한참 간소화 쿼리 만들고 있는데... join - partition 은 생각 못하고 있었네요..
제 나름 간소화한 쿼리 입니다.
Select a.code_a_pk, b.code_id, b.code_nm From (select distinct code_a_pk from CodeA) a inner join (select distinct code_id, code_nm from CodeB) b left outer join CodeA c on a.code_a_pk = c.code_a_pk and b.code_id = c.code_id where c.code_id is null order by 1, 2
INNER JOIN 만 CROSS JOIN 으로 바꾸면 의미가 명확해질 듯 합니다.
PARTITION JOIN 기능이 없다면? 이렇게 하는게 맞습니다.
B 에 중복은 없다고 가정하고 Distinct 는 빼도 될 듯 하네요.
네. cross join 이 제가 테스트하는 웹 사이트에서 적용이 안되어 조건없는 inner 로 처리했네요.
덕분에 좋은 방법 하나 배워갑니다.
마농님,우주민님 도움주셔서 감사합니다.!!