DB/MySQL

[MySQL] UNION, UNION ALL

동호다찌 2022. 4. 6. 19:24

MySQL 등의 RDBMS에서 사용하는 Union 연산자는 여러 테이블에 존재는 같은 성격의 값을 한 번의 쿼리로 추출할 수 있도록 돕는다.

예를 들어 Member 테이블에 회원 이메일이 있고, Newsletter 테이블에 구독자 이메일이 있는데, 모든 이메일로 메일을 보내고자 할 경우 두 번의 쿼리와 병합 프로그램을 만들어야 할 것이다. 이럴 때 union 연산자를 사용하면 한 번의 쿼리로 간단하게 정보를 추출할 수 있다.


* Member

 seq  u_name  u_email   etc 
 1  홍길동  aa@aa.co.kr  ...
 2  이순신  bb@bb.co.kr  ...
 3  세종대왕  cc@cc.co.kr  ...


* Newsletter 

letter_ seq  letter_name  letter_email   letter_etc 
 1  테스트1  aa@aa.co.kr  ...
 2  테스트2  dd@d.co.kr  ...
 3  테스트3  ee@ee.co.kr  ...


위의 2개 테이블에서 이메일을 추출해야 할 경우 union을 사용하면 간단하다.

중복되지 않은 유일한 정보 만 추출하는 경우

Union을 사용하는 경우 대응되는 각 필드의 이름을 같게 맞추어 쿼리를 한다.

(SELECT u_name, 
	    u_email 
   FROM Member 
  WHERE seq < 10 )
UNION
( SELECT letter_name AS u_name, 
         letter_email AS u_email 
    FROM Newsletter 
   WHERE letter_seq < 10 )


이렇게 쿼리를 하면 이름(user_name)과 이메일(user_email)이 같은 경우 하나의 값 만 추출하여 DISTINCT 함수와 같은 효과를 준다.

중복되더라도 모든 값을 추출하는 경우

만약 중복되더라도 모든 정보를 추출해야 한다면 Union ALL 연산자를 이용하면 된다.

( SELECT u_name, 
         u_email 
    FROM Member 
   WHERE seq < 10 )
UNION ALL
( SELECT letter_name AS u_name, 
         letter_email AS u_email 
    FROM Newsletter 
   WHERE letter_seq < 10 )

 

UNION을 하면 결과가 테이블에 종속되는 것이 아니다. 그러므로 결과를 정렬을 해야 한다면 쿼리의 끝에 정렬을
추가하면 된다.

( SELECT u_name, 
         u_email 
    FROM Member 
   WHERE seq < 10 )
UNION
( SELECT letter_name AS u_name, 
         letter_email AS u_email 
    FROM Newsletter 
   WHERE letter_seq < 10 )
ORDER BY u_email



이렇게 추출할 경우 중복되지 않은 유일한 정보 만을 추출하는 경우와 중복되더라도 모두 추출하는 경우가 있을 것이다.

UNION과 UNION ALL은 두 개의 SQL을 하나의 SQL로 합쳐주는 역할을 수행합니다.

하지만 UNION과 UNION ALL은 중요한 차이점이 있습니다. 

 

UNION은 두 개의 SQL의 중복되는 결과 값은 보여주지 않지만 UNION ALL은 중복 되는 결과까지 모두 보여줍니다.

UNION을 사용할 때는 주요해야 할 점이 있는데 A와 B라는 두 개의 테이블을 합친다고 가정을 한다면

1. A와 B테이블의 컬럼 수는 동일해야 합니다.

(칼럼 명은 동일하지 않아도 문제는 없지만 'AS'를 사용하여 맞춰주는 것이 좋다)

2. 대응하는 칼럼들의 Type이 같아야 합니다.

 
SELECT name, age FROM userTB
union
SELECT name, age FROM boardTB