본문 바로가기

📚Study Note/ORACLE

[ ORACLE ] JOIN - UNION UNION ALL INTERSECT MINUS

SELECT USER
FROM DUAL;
--==>>  SCOTT


-- ■■■ UNION / UNION ALL ■■■■

-- ● 실습 테이블 생성(TBL_JUMUN)
CREATE TABLE TBL_JUMUN -- 주문번호, 주문된제품코드, 주문수량, 주문일자
( JUNO      NUMBER  
, JECODE    VARCHAR2(30)
, JUSU      NUMBER
, JUDAY     DATE DEFAULT SYSDATE

);

--Table TBL_JUMUN이(가) 생성되었습니다.

--> 고객의 주문이 발생했을 경우 주문내용에 대한 데이터가 입력될 수 있는 테이블


-- ● 데이터 입력 → 고객의 주문 발생/ 접수

INSERT INTO TBL_JUMUN VALUES
(1, '쫀득초코칩', 20, TO_DATE('2001-11-01 09:05:12','YYYY-MM-DD HH24:MI:SS'));


INSERT INTO TBL_JUMUN VALUES
(2, '와클', 10, TO_DATE('2001-11-01 09:23:37','YYYY-MM-DD HH24:MI:SS'));


INSERT INTO TBL_JUMUN VALUES
(3, '꼬북칩', 30, TO_DATE('2001-11-01 11:41:00','YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN VALUES
(4, '칙촉', 12, TO_DATE('2001-11-02 10:22:00','YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN VALUES
(5, '홈런볼', 50, TO_DATE('2001-11-03 15:50:00','YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN VALUES
(6, '바나나킥', 40, TO_DATE('2001-11-04 11:10:00','YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN VALUES
(7, '눈을감자', 10, TO_DATE('2001-11-10 10:10:10','YYYY-MM-DD HH24:MI:SS'));


INSERT INTO TBL_JUMUN VALUES
(8, '포카칩', 40, TO_DATE('2001-11-13 09:41:14','YYYY-MM-DD HH24:MI:SS'));

INSERT INTO TBL_JUMUN VALUES
(9, '감자칩', 20, TO_DATE('2001-11-14 14:20:00','YYYY-MM-DD HH24:MI:SS'));


INSERT INTO TBL_JUMUN VALUES
(10, '칸쵸', 20, TO_DATE('2001-11-20 14:17:00','YYYY-MM-DD HH24:MI:SS'));



ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
--==>>Session이(가) 변경되었습니다.


-- ● 확인
SELECT *
FROM TBL_JUMUN;

/*
1	쫀득초코칩	20	    2001-11-01 09:05:12
2	와클	    10	    2001-11-01 09:23:37
3	꼬북칩	    30	    2001-11-01 11:41:00
4	칙촉      	12	    2001-11-02 10:22:00
5	홈런볼	    50	    2001-11-03 15:50:00
6	바나나킥	40	    2001-11-04 11:10:00
7	눈을감자	    10	    2001-11-10 10:10:10
8	포카칩	    40	    2001-11-13 09:41:14
9	감자칩	    20	    2001-11-14 14:20:00
10	칸쵸	    20	    2001-11-20 14:17:00



*/

COMMIT;--==>>커밋 완료.


-- ● 데이터 추가 입력 → 2001 년 부터 시작된 주문이 현재(2021)년까지 계속 발생

INSERT INTO TBL_JUMUN VALUES(938765,'홈런볼', 10, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938766,'빈츠', 10, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938767,'와클', 10, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938768,'홈런볼', 50, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938769,'꼬북칩', 30, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938770,'꼬북칩', 20, SYSDATE);--1 행 이(가) 삽입되었습니다.

INSERT INTO TBL_JUMUN VALUES(938771,'포카칩', 40, SYSDATE);--1 행 이(가) 삽입되었습니다.
INSERT INTO TBL_JUMUN VALUES(938771,'꼬북칩', 10, SYSDATE);
INSERT INTO TBL_JUMUN VALUES(938772,'포카칩', 40, SYSDATE);
INSERT INTO TBL_JUMUN VALUES(938773,'꼬북칩', 20, SYSDATE);
INSERT INTO TBL_JUMUN VALUES(938774,'칸쵸', 20, SYSDATE);
INSERT INTO TBL_JUMUN VALUES(938775,'칸쵸', 10, SYSDATE);
INSERT INTO TBL_JUMUN VALUES(938776,'바나나킥', 10, SYSDATE);

/*
1	    쫀득초코칩	20	2001-11-01 09:05:12
2	    와클	        10	2001-11-01 09:23:37
3	    꼬북칩	    30	2001-11-01 11:41:00
4	    칙촉      	12	2001-11-02 10:22:00
5	    홈런볼	    50	2001-11-03 15:50:00
6	    바나나킥    	40	2001-11-04 11:10:00
7	    눈을감자	    10	2001-11-10 10:10:10
8	    포카칩	    40	2001-11-13 09:41:14
9	    감자칩	    20	2001-11-14 14:20:00
10	    칸쵸      	20	2001-11-20 14:17:00
938765	홈런볼	    10	2021-04-01 14:23:18
938766	빈츠      	10	2021-04-01 14:24:15
938767	와클	        10	2021-04-01 14:24:59
938768	홈런볼	    50	2021-04-01 14:25:25
938769	꼬북칩	    30	2021-04-01 14:25:49
938770	꼬북칩	    20	2021-04-01 14:26:49
938771	꼬북칩	    10	2021-04-01 14:32:17
938772	포카칩	    40	2021-04-01 14:32:19
938773	꼬북칩	    20	2021-04-01 14:32:21
938774	칸쵸	        20	2021-04-01 14:32:22
938775	칸쵸      	10	2021-04-01 14:32:23
*/

-- ※ 유림이가 2001 년도 부터 과자 쇼핑몰

-- TBL_JUMUN 테이블이 너무 무거워진 상황
-- 어플리케이션과의 연동으로 인해 주문 내역을 다른 테이블에 저장할 수 있도록
-- 만드는 것은 힘든 상황
-- 기존의 모든 데이터를 덮어놓고 지우는 것도 불가능한 상황
-- → 결과적으로 ... 현재까지 누적된 주문 데이터 중
-- 금일 발생한 주문 내역을 제외하고 
-- 나머지를 다른 테이블(TBL_JUMUNBACKUP) 로
-- 데이터 이관을 수행할 계획

CREATE TABLE TBL_JUMUNBACKUP
( JUNO  NUMBER  
, JECODE VARCHAR2(30)
,JUSU   NUMBER
,JUDAY  DATE DEFAULT SYSDATE

);
--==>>Table TBL_JUMUNBACKUP이(가) 생성되었습니다.

DROP TABLE TBL_JUMUNBACKUP;





CREATE TABLE TBL_JUMUNBACKUP
AS
SELECT *
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY,'YYYY-MM-DD') != TO_CHAR(SYSDATE,'YYYY-MM-DD');

SELECT *
FROM TBL_JUMUNBACKUP;

/*
1	쫀득초코칩	20	2001-11-01 09:05:12
2	와클	10	2001-11-01 09:23:37
3	꼬북칩	30	2001-11-01 11:41:00
4	칙촉	12	2001-11-02 10:22:00
5	홈런볼	50	2001-11-03 15:50:00
6	바나나킥	40	2001-11-04 11:10:00
7	눈을감자	10	2001-11-10 10:10:10
8	포카칩	40	2001-11-13 09:41:14
9	감자칩	20	2001-11-14 14:20:00
10	칸쵸	20	2001-11-20 14:17:00
*/


--> TBL_JUMUN 테이블의 데이터들 중
--금일 주문내역 이외의 데이터는 모두 TBL_JUMUNBACKUP 테이블에 백업을 마친 상태

--> TBL_JUMUN 테이블의 데이터들 중
--금일 주문내역 이외의 데이터는 모두 삭제

DELETE
FROM TBL_JUMUN
WHERE TO_CHAR(JUDAY,'YYYY-MM-DD') != TO_CHAR(SYSDATE,'YYYY-MM-DD');
--===>>10개 행 이(가) 삭제되었습니다. (938762 건의 데이터 삭제)

-- 아직 제품 발송이 완료되지 않은 금일 주문 데이터를 제외하고
-- 이전의 모든 주문 데이터들이 삭제된 상황이므로
-- 테이블은 행(레코드)의 갯수가 줄어들어 매우 가벼워진 상황.


SELECT *
FROM TBL_JUMUN;
/*
938765	홈런볼	10	2021-04-01 14:23:18
938766	빈츠	    10	2021-04-01 14:24:15
938767	와클	    10	2021-04-01 14:24:59
938768	홈런볼	50	2021-04-01 14:25:25
938769	꼬북칩	30	2021-04-01 14:25:49
938770	꼬북칩	20	2021-04-01 14:26:49
938771	꼬북칩	10	2021-04-01 14:32:17
938772	포카칩	40	2021-04-01 14:32:19
938773	꼬북칩	20	2021-04-01 14:32:21
938774	칸쵸	    20	2021-04-01 14:32:22
938775	칸쵸	    10	2021-04-01 14:32:23
938776	바나나킥	10	2021-04-01 14:32:25
*/


COMMIT;--커밋 완료.


-- 그런데 지금까지 주문받은 내역에 대한 정보를 
-- 제품별 총 주문량으로 나타내야 할 상황이 발생하게 되었다.
-- 그렇다면... TBL_JUMUNBACKUP 테이블의 레코드(행)와
-- TBL_JUMUN 테이블의 레코드(행)를 합쳐서
-- 하나의 테이블을 조회하는 것 과 같은
-- 결과를 확인할 수 있도록 조회해야 한다,

-- 컬럼과 컬럼의 관계를 고려하여 테이블을 결합하고자 하는 경우 JOIN 을 사용하지만
-- 레코드(행)와 레코드를 결합하고자 하는 경우 UNION/ UNION ALL 을 사용할 수 있다.

SELECT *
FROM TBL_JUMUNBACKUP
UNION ALL
SELECT *
FROM TBL_JUMUN
ORDER BY 2;



SELECT *
FROM TBL_JUMUNBACKUP
UNION 
SELECT *
FROM TBL_JUMUN;





--[위에 두개 복붙]
SELECT *
FROM TBL_JUMUN
UNION ALL
SELECT *
FROM TBL_JUMUNBACKUP;


SELECT *
FROM TBL_JUMUN
UNION 
SELECT *
FROM TBL_JUMUNBACKUP;

/*성능은 ALL이 좋다 정렬기능이없으니까 
UNION은 정렬도 해주고 중복된거있으면 하나만 나온다. 
UNION ALL 은 그냥 생각안하고 그냥 막 갖다붙이는거다. 그래서 정렬도 안하고 중복도 제거안한다.
그런데 성능이 더 좋아서 ALL을 많이 사용한다. 
    
/*
UNION은 항상 결과물의 첫 번째 컬럼을 기준으로 오름차순 정렬을 수행한다.
UNION ALL 은 결합된 순서대로 조회한 결과를 반환한다. (정렬 없음)
이론 인해 UNION은 부하가 더 크다.
또한, UNION은 결과물에서 중복된 행이 존재할 경우
중복을 제거하고 1개 행만 조회된 결과를 반환하게 된다.*/


-- ● 지금까지 주문받은 모든 데이터를 통해
-- 제품별 총 주문량을 조회하는 쿼리문을 구성한다. 

SELECT SUM(JUSU)
FROM TBL_JUMUN
UNION ALL
SELECT SUM(JUSU)
FROM TBL_JUMUNBACKUP
GROUP BY JECODE;
/*
ORA-00937: not a single-group group function
00937. 00000 -  "not a single-group group function"
*Cause:    
*Action:
274행, 8열에서 오류 발생
*/



SELECT JECODE, SUM(JUSU)
FROM TBL_JUMUN
UNION ALL
SELECT JECODE, SUM(JUSU)
FROM TBL_JUMUNBACKUP
WHERE TBL_JUMUN.JECODE = TBL_JUMUNBACKUP.JECODE
GROUP BY JECODE;



SELECT T.JECODE"제품코드", SUM(T.JUSU)"총주문량"
FROM(
    SELECT *
    FROM TBL_JUMUN
    UNION ALL
    SELECT *
    FROM TBL_JUMUNBACKUP
)T
GROUP BY JECODE;

/*
꼬북칩	    90
쫀득초코칩	20
와클	        20
포카칩	    100
칙촉	        12
바나나킥	    50
눈을감자	    10
홈런볼	    110
빈츠  	    10
감자칩	    20
칸쵸	        50
*/




SELECT T.JECODE"제품코드", SUM(T.JUSU)"총주문량"
FROM(
    SELECT JECODE,JUSU
    FROM TBL_JUMUN
    UNION 
    SELECT JECODE, JUSU
    FROM TBL_JUMUNBACKUP
)T
GROUP BY JECODE;
/*
꼬북칩	60
쫀득초코칩	20
와클	10
칙촉	12
포카칩	60
눈을감자	10
바나나킥	50
감자칩	20
빈츠	10
홈런볼	60
칸쵸	30*/


-- 이 문제를 해결하는 과정에서는 UNION을 사용해서는 안된다
-- JECODE 와 JUSU를 조회하는 과정에서 중복된 행을 제거하는 상황이 발생



--● INTERSECT / MINUS ( → 교집합/차집합)

-- TBL_JUMUNBACKUP 테이블과 TBL_JUMUN 테이블에서
-- 제품코드와 주문량의 값이 똑같은 행만 추출하고자 한다.




SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP;

/*
쫀득초코칩	20
와클	10
꼬북칩	30
칙촉	12
홈런볼	50
바나나킥	40
눈을감자	10
포카칩	40
감자칩	20
칸쵸	20*/

SELECT JECODE, JUSU
FROM TBL_JUMUN;
/*
홈런볼	10
빈츠	10
와클	10
홈런볼	50
꼬북칩	30
꼬북칩	20
꼬북칩	10
포카칩	40
포카칩	20
칸쵸	20
칸쵸	10
바나나킥	10*/



SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP
INTERSECT
SELECT JECODE, JUSU
FROM TBL_JUMUN;
/*
꼬북칩	30
와클  	10
칸쵸  	20
포카칩	40
홈런볼	50*/


-- 두 테이블에서 제품코드와 주문량의 값이 똑같은 행의 정보를
-- 주문번호, 제품코드, 주문수량, 주문일자 항목으로 조회한다.

SELECT S.JUNO, S.JECODE, S.JUSU, S.JUDAY
FROM
(
SELECT T.JUNO,T.JECODE, T.JUSU, T.JUDAY
, (
    SELECT COUNT(*)
    FROM
        (SELECT JECODE, JUSU
         FROM TBL_JUMUNBACKUP
         INTERSECT
         SELECT JECODE, JUSU
         FROM TBL_JUMUN)A
    WHERE T.JECODE=A.JECODE AND T.JUSU=A.JUSU  )"SAME_JECODE_JESU" 
    
    
    
FROM(  
    SELECT *
    FROM TBL_JUMUNBACKUP
    UNION ALL
    SELECT *
    FROM TBL_JUMUN
)T
)S
WHERE S.SAME_JECODE_JESU=1;

 

 

MINUS (1열~10열 / 11열 ~ 22열 사이의 차집합을 구한다.)

SELECT JECODE, JUSU
FROM TBL_JUMUNBACKUP
MINUS
SELECT JECODE, JUSU
FROM TBL_JUMUN;

/*

감자칩	20
눈을감자	10
바나나킥	40
쫀득초코칩	20
칙촉	12*/