SQL을 어느 정도 공부해보신 분이라면 JOIN에 대해 많이 익숙해져 있으실텐데요. 일반적으로 조인 조건에는 동등 연산자(=)를 사용하지만 오늘은 테이블 간에 컬럼이 서로 정확하게 일치하지 않을 때 사용하는 비등가 조인(Non-Equi Join)에 대해서 알아보도록 하겠습니다.
우선 용어부터 생소한 비등가 조인(Non-Equi Join)에 대해서 간단하게 설명 후 어떻게 적용되는지 말씀 드리겠습니다.
비등가 조인(Non-Equi Join)이란?
- 두 개이상의 테이블을 연결할 때 사용하는 조인 시에 테이블 간에 컬럼 값들이 서로 정확하게 일치하지 않는 경우 사용된다
- '=' 연산자가 아닌 다른 관계 연산자(>,>=,<,<=,!= 등)을 이용하여 JOIN을 수행하게 된다.
용어에 대한 이해가 조금은 되셨나요? 굳이 비교하자면 우리가 동등 관계 연산자(=)를 활용해 일반적으로 많이 사용해왔던 조인 방법은 등가 조인(Equi Join)이라고 말할 수 있습니다. 여기서는 이와 반대되는 개념인 비등가 조인을 사용하는 것인데요. 관련해서 solvesql이라는 SQL 문제풀이 플랫폼의 '멘토링 짝꿍 리스트' 문제를 통해 비등가 조인 방법을 소개해보겠습니다. 문제 내용에 대해서는 저작권 이슈가 있기 때문에 상세한 문제 설명은 아래 링크를 클릭해서 문제를 읽어보고 충분히 이해한 뒤 따라와주시면 감사하겠습니다.
문제는 회사에서 멘토링 프로그램을 진행하기 위해 멘토-멘티를 선정해야 하는 상황이라고 가정합니다. 주어진 사원명부(employees) 테이블에는 직원들의 사원ID, 이름, 입사일자, 부서 등의 정보가 나와 있는데요.
문제를 풀기 위해서 우리가 고려해야할 사항은 다음과 같습니다.
1. 멘토-멘티 리스트를 출력(멘티ID, 멘티 이름, 멘토ID, 멘토 이름)
2. 멘티는 2021년 12월 31일 기준 3개월 이내 신규 입사자에 해당
3. 멘토는 2021년 12월 31일 기준 재직기간이 2년 이상된 직원에 해당
4. 같은 부서에 속한 직원들 간에는 멘토-멘티가 될 수 없음
5. 멘티ID 기준으로 오름차순 정렬하고, 멘티 1명에 대해 배정 가능한 멘토가 여러명일 경우 멘토 ID로 오름차순 정렬
우선 오늘의 주제이자 가장 중요한 부분인 비등가 조인을 어디서 해야할 지 눈치 채셨나요? 그럼 하나씩 차근차근 설명을 해보겠습니다. 먼저 문제에서 주어진 테이블이 1개밖에 없기 때문에 조인을 하기 위해서 하나의 테이블을 셀프조인 해주어야 하는데요. 그런데 사원ID를 기준으로 평소 처럼 동등 연산자(=)를 사용해서 셀프조인을 하게 되면 내가 나를 조인하는 것이기 때문에 멘토-멘티 관계가 형성될 수 없습니다.
그러므로 이럴때 사원ID를 기준으로 '사원ID가 같지 않은 경우(!=)'를 의미하는 비등가 조인(Non-Equi Join)을 사용해주면 내 사원ID를 제외한 모든 사원ID가 조인되게 됩니다. 아직 잘 이해가 가지 않는다면 우선 아래 쿼리를 실행해보시면 됩니다.
SELECT *
FROM employees a LEFT JOIN employees b ON a.employee_id != b.employee_id
여기까지 이해가 되셨다면 위에서 언급한 문제의 조건을 하나하나 해결해 나가겠습니다. 우선 멘티는 기준 날짜로부터 3개월 내 신규 입사자에 해당하는 조건이어야 하고, 멘토는 기준 날짜로 부터 재직기간이 2년 이상된 직원이어야 합니다. 그렇기 때문에 입사일자를 기준으로 WHERE 절에 다음과 같은 조건을 걸어볼 수 있습니다.
SELECT *
FROM employees a LEFT JOIN employees b ON a.employee_id != b.employee_id
WHERE a.join_date > '2021-09-31'
AND b.join_date < '2020-01-01'
그리고 같은 부서에 속한 직원들 간에는 멘토-멘티가 될 수 없다고 했기 때문에 WHERE 절에 추가로 해당 조건을 걸어준 다음 정렬은 멘티ID, 멘토ID 순으로 오름차순 정렬을 해줍니다. 마지막으로 출력은 멘티/멘토 ID와 이름만 해주면 되기 때문에 입사일자, 부서명 등은 제외하고 출력될 수 있게끔 아래와 같이 최종 쿼리를 작성해주면 되겠습니다.
SELECT a.employee_id AS mentee_id
, a.name AS mentee_name
, b.employee_id AS mentor_id
, b.name AS mentor_name
FROM employees a LEFT JOIN employees b ON a.join_date != b.join_date
WHERE a.join_date > '2021-09-31'
AND b.join_date < '2020-01-01'
AND a.department != b.department
ORDER BY mentee_id, mentor_id
저도 해당 문제를 풀기 전까지 비등가 조인에 대한 개념을 전혀 몰라서 어떻게 JOIN해야 할지 굉장히 난감했었는데요. 비등가 조인에 대한 개념만 알고 있으면 막상 문제를 해결하는데는 큰 어려움이 없었던 것 같습니다. 실무에서 활용 빈도가 높아보이지는 않지만 알아두면 언젠가는 유용하게 쓸 수 있을 것 같네요!
작성된 내용 중 잘못된 부분이나 궁금한 사항이 있다면 언제든지 피드백 부탁 드립니다.
감사합니다.
'Data > SQL' 카테고리의 다른 글
SQL 고급 : 윈도우 함수(분석 함수) - LAG(), LEAD() (0) | 2022.03.28 |
---|---|
SQL 고급 : PIVOT TABLE (0) | 2022.03.22 |
SQL 고급 : 윈도우 함수(순위 함수) - RANK(), DENSE_RANK(), ROW_NUMBER() (0) | 2022.03.17 |
SQL 고급 : 3개 이상의 테이블을 JOIN 하기 (0) | 2022.03.15 |
SQL 실무 : DAU 및 신규, 복귀, 기존 유저 구별하기 (3) | 2022.03.07 |