join에 본격적으로 들어가기 전에 집합연산자를 먼저 살펴보자.
집합연산자는 select문 결과를 하나의 집합으로 합쳐야 하거나, 여러 select문의 결과에 대한 합집합, 교집합, 차집합을 연산한다.
집합연산자는 select문과 select문 사이에 쓰인다. 즉, 위치가 정해져 있다.
집합연산자의 종류로 세 가지가 있다.
1) union / union all: 합집합
유사한 두 테이블이 있을 때 또는 완전히 분리되어있는 세트를 세로로 결합할 때 합집합으로 계산한다.
예를 들어, 10번 부서 정보와 20번 부서 정보가 각각 분리되어있다고 가정할 때, 합집합으로 정보를 모아보자.
이런 형태로 쓸 수 있다.
2) intersect: 교집합
교집합도 예시로 살펴보자.
10번 부서 정보가 아닌 부서원 집합과(20, 30번 부서) 20번 부서 정보가 아닌 부서원 집합(10, 30번 부서)의 교집합을 구하면
이렇게 공통 부서인 30번 부서가 출력된다.
3) minus: 차집합
예시로, 20, 30번 부서원 데이터에서 20번 부서원의 차집합을 구하면 다음과 같다.
위 세 가지에서 중요한 것은 두 집합의 정보(컬럼)가 select에 동일하게 구성이 되어야 한다는 것이다.
위 집합인 select는 empno, ename, sal, deptno, sal 가 구성되어있고, 아래 집합 select에는 empno, ename, sal, deptno가 구성된다면 짝이 맞지 않아 부정확환 열의 수를 가지고 있다는 에러가 뜬다. 그 외에도 순서도 동일하여야 한다.
예제를 하나 풀어보자.
emp_t1테이블을 만들고 emp 테이블과의 세 가지 집합을 연산해보자.
여기서 테이블을 만드는 코드는 다음과 같다.
as 의 ~ 처럼 뜻과 같이 본 코드는 emp 테이블 처럼 emp_t1테이블을 만들라는 의미이며 각 앞 자리의 영문을 따와서 ctas문법이라고 칭한다. 현업에서 많이 사용하는 코드이며 이 코드는 백업할 때 종종 사용된다.
첫 번째 union 사용하여 합집합 구하기.
무작정 union 결합하니 에러가 생겼다. 두 테이블을 각각 열어보니 컬럼 수가 달랐다.
컬럼 수를 아래와 같이 맞추고 실행했는데 또 에러가 생겼다.
empno에 표시가 되어있는 걸 보니 저기서 문제가 생긴 것이다.
desc를 사용하여 테이블 변수 정보를 확인해보니 위 아래 집합의 empno 데이터 타입이 달랐다.
그래서 하나로 통일시켜야 한다. 그럼 어디를 바꾸어 주는 것이 좋을까.
둘 다 숫자로 바꾸거나 문자로 바꾸면 되는데, 집합 연산자의 경우 위에 있는 select(집합)이 최종 출력되는 집합의 컬럼 이름과 데이터 타입으로 변하기 때문에 바꾸고자 하는 곳에 to_number 나 to_char로 변경하면 되겠다.
이렇게 바꾸니 해결되었다.
이쯤되면 궁금한 것.. 합집합은 왜 union과 union all 두 종류가 있을까?
A집합 B집합의 교집합이 있을 때 union으로 처리하면 중복값은 하나만 표기된다(중복값 제거).
union all은 중복을 허용하여 전체 집합의 합집합을 리턴하게 된다.
★여기서 중복제거 매커니즘이 중요하다. 튜닝 성능에 영향을 주기 때문이다. union이 중복값을 제거할 때 사전에 정렬을 한다. distinct도 중복값을 출력할 때 생략하여 출력하는데 이 때 distinct도 정렬을 한다.
온전히 중복이 없는 데이터의 경우에는 아래처럼 union all을 쓰면 좋다.
우리가 기존에 ★중복값이 없다는 걸 인지하고 있는 경우 union all을 써야한다. union을 쓰면 중복값을 찾기 위해 불필요한 정렬을 수행하게 되고 이 때 성능저하가 동반된다.
다른 언어에서는 union all이라는 개념이 없어서 보통 개발자들은 그냥 union을 쓰기도 한다.
SQL을 사용할 때에는 두 차이를 신경써야 한다.
정리하자면 union / union all 결과가 동일할 경우 union all을 사용한다.
연습문제를 하나 풀어보자.
emp 테이블의 정보와 emp2 테이블 정보를 한 번에 출력하고자 한다. 이 때 사원이름, 사원번호, 부서번호, 급여를 출력하는데 급여는 모두 단위를 원으로 한다(emp의 sal은 단위가 만원이라 가정).
이렇게 출력하면 되겠다.
여기까지가 집합연산자이고 조금 쉬었다가 다음 게시물에서 join을 복습해봐야겠다.
'배우기 > 복습노트[oracle sql]' 카테고리의 다른 글
[복습] SQL | Oracle 첫 번째 마주한 큰 산, join (2) + 복습후기(20231101) (0) | 2023.11.01 |
---|---|
[복습] SQL | Oracle 첫 번째 마주한 큰 산, join (1) (0) | 2023.11.01 |
[복습] SQL | Oracle 그룹별 연산을 하기 위한 group by 와 having + 복습후기(20231031) (0) | 2023.10.31 |
[복습] SQL | Oracle 조건을 나타내기, 일반함수(decode, case) (0) | 2023.10.31 |
[실습문제] 2023. 10. 30.(월) 문제 풀이(7문제) (0) | 2023.10.31 |