세미조인
메인 쿼리에서 사용된 테이블과 서브쿼리 결과를 조인하는 조인을 의미한다.
먼저 세미 조인은 말 그대로 조인과 유사한 연결방법을 의미한다. 위에서 말했다 싶이 세미조인의 조인 대상은 SELECT문으로 추출된 테이블을 의미한다.
예시를 보면 다음과 같다.
EXISTS 연산자를 사용한 세미조인
SELECT *
FROM dept_master a
WHERE EXISTS (SELECT
FROM emp_master b
WHERE b.age BETWEEN 40 AND 49
AND a.dept_id = b.dept_id
);
Exists연산자는 메인쿼리의 테이블 데이터를 기준으로 서브쿼리에서 반환하는 데이터가 존재하면 참을 반환합니다.
INNER JOIN vs SEMI JOIN
INNER JOIN과 SEMI JOIN의 차이는 1 : N관계의 테이블을 조인할 때 그 특징이 뚜렷해진다.
다음과 같은 관계가 있고 우리가 현재 학생들이 있는 학과만 추출하고 싶다고 가정해보자
SELECT d.dept_name
FROM department d
INNER JOIN student s ON s.dept_code = d.dept_code;
위와 같이 SQL쿼리문을 짜면 어떻게 될까?
이런식으로 결과가 출력된다.
왜 이럴까? JOIN을 진행하고 JOIN이 끝난 테이블에서 dept_name을 추출했기 때문이다.
물론 groupby나 distinct를 사용하면 해당 문제를 해결할 수 있지만 이는 속도 저하 문제가 생길 수 있다.
우리가 원하는 쿼리 처리 과정은 특정 과 이름을 가지고 student table을 순회하다가 같은 이름이 있는 경우 dept_name으로 가져오게 되는 것을 상상할 것이다. 하지만 join의 경우 전체 테이블 데이터를 가져온 후에 이를 join하고 후처리를 하기 때문에 우리가 상상했던 방식과는 사뭇 다르다.
이럴 때 사용할 수 있는게 세미 조인이다.
SELECT d.dept_name
FROM department d
WHERE d.dept_code IN (SELECT s.dept_code FROM student s);
이렇게 코드를 짜면 서브 쿼리로 인해 가져온 student 테이블에 있는 dept_code 중에 dept_code가 있다면 해당 dept_name이 선정된다.
따라서 department를 순회하면서 student table에 해당 데이터가 있다면 통과가 된다.
그렇기 때문에 속도가 더 빠를 것이다. 아래와 같이 확인해보자.
안티조인
안티조인은 SELECT한 조건 문과 JOIN을 한다는 점에서 유사할 수는 있지만 세미조인과 달리 SELECT문으로 택해진 데이터 이외의 데이터 들과 메인 쿼리의 테이블이 조인을 하는 연결방식을 의미한다.
NOT 연산자를 사용한 안티조인
SELECT *
FROM dept_master a
WHERE a.dept_id NOT IN (
SELECT b.dept_id
FROM emp_master b
WHERE b.age BETWEEN 40 AND 49
);
이렇게 하면 40대가 아닌 사원들에 대해서 join을 하게 된다.
NOT EXISTS를 사용한 안티조인
SELECT *
FROM dept_master a
WHERE NOT EXISTS (
SELECT 1
FROM emp_master b
WHERE b.age BETWEEN 40 AND 49
AND a.dept_id = b.dept_id
);
위와 같지만 NOT EXISTS를 사용해서 안티조인을 한 결과이다.
본 글은 '누구나 쉽게 SQL'이라는 책을 읽고 정리한 내용입니다.
http://www.yes24.com/Product/Goods/74311553
더 많은 내용을 알고 싶은 분은 위의 책을 보시길 바랍니다.
긴 글 읽어주셔서 감사합니다.
틀린 부분이 있으면 댓글을 달아주시면 감사하겠습니다.
📧 : may3210@g.skku.edu
'개발 > Oracle' 카테고리의 다른 글
[Database] 데이터 입력과 삭제 그리고 수정 (0) | 2022.02.15 |
---|---|
[Database] 서브 쿼리 (0) | 2022.02.15 |
[Database] 테이블 간 관계 맺기 - 외부 조인과 카티션 곱 (0) | 2022.02.15 |
[Database] 테이블 간 관계 맺기 - 내부 조인 (0) | 2022.02.15 |
[Database] 집합 쿼리 (0) | 2022.02.15 |