모던지 / SQL 개발자 / SQL 기본 및 활용 6강. 조인의 원리

SQL 기본 및 활용 6강. 조인의 원리

조인 조건을 빼먹으면 오류가 나지 않습니다. 대신 두 테이블의 모든 조합이 나옵니다. 천 건과 천 건이면 백만 건이죠.

풀고 시작

문제 1. 두 테이블을 FROM 절에 나열하고 조인 조건을 쓰지 않았을 때 만들어지는 결과는?
조인 조건이 없으면 모든 조합이 만들어지는 카티션 곱이 됩니다. 오류가 나지 않기 때문에 더 위험합니다. 결과 건수가 두 테이블 행 수의 곱이 되므로 조건 누락은 성능 사고로 곧장 이어집니다.

조인은 모델의 관계선을 문장으로 옮긴 것

1과목 6강에서 이야기한 그 자리입니다. 정규화로 나눠 둔 집합을 다시 이어 붙이는 일이 조인입니다. 부모의 식별자가 자식에게 상속되어 있으니 그 값이 같은 행끼리 맞붙이면 됩니다.

그래서 조인을 배울 때 문법보다 먼저 잡아야 하는 감각은 어떤 컬럼이 두 테이블을 잇는 고리인가입니다. 사원과 부서를 이으려면 부서코드가 고리이고, 주문과 주문상세를 이으려면 주문번호가 고리입니다. 이 고리를 찾는 능력은 SQL 문법이 아니라 모델을 읽는 능력이죠.

조인은 한 번에 두 집합씩 처리됩니다. 테이블 네 개를 조인하면 데이터베이스는 두 개를 먼저 붙여 중간 결과를 만들고, 거기에 세 번째를 붙이고, 다시 네 번째를 붙입니다. 그래서 N개의 테이블을 조인하려면 최소 N에서 1을 뺀 개수의 조인 조건이 필요합니다. 조건이 그보다 적으면 어딘가에서 모든 조합이 만들어집니다.

EQUI 조인과 NON EQUI 조인

조인 조건에 등호를 쓰면 EQUI 조인입니다. 실무의 거의 모든 조인이 여기에 해당합니다. 부모의 키와 자식의 외래키가 같은 행을 붙이는 것이니 당연하죠.

등호가 아닌 연산자를 쓰면 NON EQUI 조인입니다. 언제 필요할까요. 급여 구간표를 생각해 보죠. 등급별로 하한과 상한이 정의된 표가 있고, 사원의 급여가 어느 구간에 드는지 알아내야 합니다. 이때는 급여가 하한 이상이고 상한 이하라는 조건으로 이어야 합니다. 같은 값을 찾는 것이 아니라 범위에 드는지를 찾는 것이니 등호로는 할 수 없습니다.

종류 조인 조건 쓰이는 상황
EQUI 조인 등호 비교 키와 외래키를 잇는 대부분의 경우
NON EQUI 조인 범위나 부등호 비교 구간표, 등급표, 기간 겹침 판정

카티션 곱, 사고의 대표적인 얼굴

FROM 절에 테이블을 여러 개 적고 조인 조건을 쓰지 않으면 카티션 곱(cartesian product)이 만들어집니다. 왼쪽 테이블의 모든 행이 오른쪽 테이블의 모든 행과 짝을 지어, 결과 건수가 두 테이블 행 수의 곱이 됩니다.

무서운 것은 오류가 나지 않는다는 점입니다. 문법상 완전히 정당한 쿼리이고, 실제로 필요한 경우도 있습니다. 날짜 목록과 부서 목록을 곱해 빈 조합까지 채운 보고서 틀을 만드는 것이 그 예죠. 그래서 데이터베이스는 의심하지 않고 그대로 실행합니다.

문제는 실수로 만들어졌을 때입니다. 테이블 세 개를 조인하면서 조건을 하나만 쓴 경우가 흔합니다. 두 개는 제대로 붙었는데 세 번째가 모든 조합으로 붙어, 결과 건수가 갑자기 수천 배가 되죠. 이때 나타나는 증상이 특징적입니다. 건수가 이상하게 많고, 합계가 이상하게 크고, 쿼리가 끝나지 않습니다. 조인 조건 개수부터 세어 보는 것이 첫 번째 점검입니다.

여러 테이블을 조인할 때의 실전 규칙

조인이 세 개 이상 겹치면 몇 가지 습관이 필요합니다.

테이블에 별칭을 붙이세요. 컬럼 앞에 테이블 별칭을 적어 두면 어느 테이블의 컬럼인지가 문장에 남습니다. 두 테이블에 같은 이름의 컬럼이 있으면 별칭 없이는 아예 실행되지 않고, 있어도 뒤에 읽는 사람이 추적할 수 없습니다.

조인 조건과 검색 조건을 구분해 인식하세요. 두 테이블을 잇는 조건과 특정 행을 골라내는 조건은 목적이 다릅니다. 옛 문법에서는 둘이 WHERE 절에 섞여 있어 구별이 어려운데, 다음 강에서 볼 표준 조인 문법은 이 둘을 문법적으로 갈라 줍니다. 그것이 표준 문법을 쓰는 가장 큰 이유입니다.

조인 결과의 행 수를 예상하세요. 일대일로 붙으면 건수가 유지되고, 일대다로 붙으면 다 쪽을 따라 늘어납니다. 예상보다 많으면 어딘가에서 관계가 일대다인데 일대일로 착각한 것이거나 조건이 빠진 것입니다. 이 습관 하나가 잘못된 보고서를 대부분 막아 줍니다.

그리고 셀프 조인을 잠깐 언급해 두겠습니다. 같은 테이블을 두 번 불러 서로 다른 별칭을 주고 조인하는 방식입니다. 사원과 그 사원의 관리자가 같은 사원 테이블에 있을 때 쓰죠. 문법상 특별한 것은 없고 별칭이 필수라는 점만 다릅니다. 12강 계층형 질의에서 다시 만납니다.

인출 문제

문제 1. 다섯 개의 테이블을 조인할 때 필요한 최소 조인 조건의 개수는?
N개의 테이블을 잇는 데는 최소 N에서 1을 뺀 개수의 조인 조건이 필요합니다. 조건이 그보다 적으면 어딘가에서 모든 조합이 만들어져 결과가 부풀어 오릅니다.
문제 2. NON EQUI 조인이 필요한 상황으로 가장 적절한 것은?
값이 같은 행을 찾는 것이 아니라 범위에 드는지를 판정해야 하므로 등호로는 이을 수 없습니다. 나머지 셋은 모두 키와 외래키를 등호로 잇는 EQUI 조인입니다.
문제 3. 조인 조건을 빠뜨렸을 때 나타나는 증상으로 보기 어려운 것은?
조건 없는 조인은 문법상 정당하기 때문에 오류가 나지 않습니다. 실제로 필요한 경우도 있어서 데이터베이스가 막아 주지 않고, 그래서 사람이 조건 개수를 세어 확인해야 합니다.
문제 4. 여러 테이블을 조인할 때 테이블 별칭을 붙이는 이유로 가장 적절한 것은?
별칭은 컬럼의 소속을 문장에 남겨 읽기와 유지보수를 돕고, 두 테이블에 같은 이름의 컬럼이 있을 때 모호함을 없앱니다. 성능과는 무관하며 조인 조건을 대신하지도 않습니다.

더 풀기

출제기준의 세세항목을 따라 이 강의 범위에서 새로 낸 문제입니다. 모의고사도 여기에서 뽑습니다.

묶음 1

문제 1. 조인을 가장 잘 설명한 것은?
조인은 옆으로 붙입니다. 위아래로 쌓는 것은 집합 연산자입니다.
문제 2. 조인 조건이 없는 두 테이블을 함께 조회하면 어떤 결과가 나오나요?
조건이 없으면 모든 짝을 만듭니다. 행 수가 두 테이블 행 수의 곱이 되어 순식간에 커집니다.
문제 3. 행이 각각 100건과 200건인 두 테이블을 조인 조건 없이 조회하면 결과 행 수는?
백 곱하기 이백으로 이만 행입니다. 이것이 조인 조건을 빠뜨렸을 때 벌어지는 일입니다.
문제 4. EQUI 조인을 가장 잘 설명한 것은?
같음으로 잇는 것이 EQUI 조인입니다. 부등호나 범위로 잇는 것은 NON EQUI 조인입니다.
문제 5. NON EQUI 조인이 필요한 상황으로 가장 알맞은 것은?
등급표는 하한과 상한을 가지므로 같음이 아니라 범위로 이어야 합니다. 나머지는 모두 같음 비교입니다.
문제 6. 세 개의 테이블을 조인하려면 최소 몇 개의 조인 조건이 필요한가요?
일반적으로 테이블 수보다 하나 적은 만큼의 조건이 필요합니다. 조건이 모자라면 그만큼 카티션 곱이 섞입니다.
문제 7. 다섯 개의 테이블을 조인할 때 필요한 최소 조인 조건 수는?
다섯에서 하나를 뺀 네 개입니다. 다만 순환 관계가 있으면 더 필요할 수도 있습니다.
문제 8. 부서 5건, 사원 20건이고 모든 사원이 부서를 하나씩 가질 때 부서코드로 내부 조인하면 결과 행 수는?
사원 한 명마다 부서 하나가 대응하므로 사원 수 그대로 이십 행입니다.
문제 9. 부서 5건 중 두 부서에는 사원이 없고 사원 20건은 모두 부서를 가질 때 내부 조인 결과 행 수는?
결과 행 수는 짝이 만들어지는 사원 기준으로 정해집니다. 사원이 없는 부서는 결과에 나타나지 않을 뿐 행 수를 줄이지는 않습니다.
문제 10. 같은 상황에서 부서를 기준으로 외부 조인을 하면 결과 행 수는?
사원과 짝지어진 이십 행에 사원이 없는 부서 두 행이 더해져 스물두 행입니다.

묶음 2

문제 1. 부모 테이블의 한 행에 자식 테이블의 세 행이 대응할 때 두 테이블을 조인하면 그 부모 행은 결과에 몇 번 나타나나요?
일대다 조인에서 부모의 값은 자식 행 수만큼 반복됩니다. 이 반복이 집계에서 값을 부풀리는 원인이 됩니다.
문제 2. 주문 10건이 있고 각 주문에 상세가 평균 3건씩 있을 때 주문과 주문상세를 조인하면 결과 행 수는 대략 얼마인가요?
상세 건수만큼 행이 만들어지므로 서른 행 안팎이 됩니다. 주문 금액을 이 결과에서 그대로 합치면 세 배로 부풀려집니다.
문제 3. 일대다 조인 결과에서 부모 쪽 금액을 합계하면 값이 부풀려지는 이유는?
조인은 행을 늘립니다. 부모 쪽 값을 집계하려면 자식을 먼저 묶어 한 행으로 줄이거나 서브쿼리를 써야 합니다.
문제 4. 일대다 조인에서 부모 금액을 정확히 합계하는 방법으로 가장 알맞은 것은?
행이 늘어난 뒤에 고치려 하면 어렵습니다. 늘어나기 전에 줄여 두는 것이 정석입니다. DISTINCT는 금액이 같은 서로 다른 주문까지 지워 버립니다.
문제 5. 셀프 조인을 가장 잘 설명한 것은?
같은 테이블을 두 번 등장시켜 서로 다른 역할로 씁니다. 사원과 그 사원의 관리자를 함께 보여 줄 때 씁니다.
문제 6. 셀프 조인에서 테이블 별칭이 반드시 필요한 이유는?
별칭이 없으면 사원번호가 어느 쪽 사원번호인지 알 수 없습니다. 별칭이 두 역할을 갈라 줍니다.
문제 7. 사원 10명 중 관리자가 없는 사원이 1명일 때 사원과 관리자를 내부 셀프 조인하면 결과 행 수는?
관리자가 없는 한 명은 짝을 찾지 못해 빠집니다. 그 사람도 보이게 하려면 외부 조인이 필요합니다.
문제 8. 조인 순서가 결과에 미치는 영향으로 옳은 것은?
내부 조인은 교환 법칙이 성립합니다. 다만 외부 조인이 섞이면 순서에 따라 결과가 달라질 수 있습니다.
문제 9. 조인할 때 먼저 처리하면 유리한 테이블로 가장 알맞은 것은?
중간 결과를 작게 유지하는 것이 조인 성능의 핵심입니다. 최적화기가 통계를 보고 판단하지만 원리는 같습니다.
문제 10. 조인 조건에 쓰이는 컬럼에 인덱스가 있으면 유리한 이유로 가장 알맞은 것은?
조인은 반복해서 짝을 찾는 작업입니다. 그 찾기가 빠르면 전체가 빨라집니다.

묶음 3

문제 1. 조인 조건과 필터 조건을 구분해서 보아야 하는 이유로 가장 알맞은 것은?
내부 조인에서는 둘을 섞어도 결과가 같지만 외부 조인에서는 조인 시점에 적용되는지 조인 후에 적용되는지가 결과를 가릅니다.
문제 2. 조인 결과에 중복 행이 예상보다 많다면 가장 먼저 확인할 것은?
행이 부푸는 원인은 대개 조건 누락이거나 예상과 달리 일대다인 관계입니다. 실제 데이터의 중복도를 확인해야 합니다.
문제 3. 조인 대상 컬럼의 자료형이 서로 다를 때 생길 수 있는 문제는?
문자와 숫자를 이으면 어느 쪽을 바꿀지에 따라 인덱스 사용 여부가 갈립니다. 모델 단계에서 도메인을 맞추어 두는 것이 근본 해결입니다.
문제 4. 조인 컬럼에 NULL이 있을 때 내부 조인에서 그 행은 어떻게 되나요?
NULL은 NULL과도 같다고 판정되지 않습니다. 그래서 조인 조건을 만족하지 못합니다.
문제 5. 부서 3건과 사원 9건이 있고 사원 중 3명의 부서코드가 NULL일 때 내부 조인 결과 행 수는?
부서코드가 있는 여섯 명만 짝을 찾습니다. NULL인 세 명은 빠집니다.
문제 6. 같은 상황에서 사원을 기준으로 왼쪽 외부 조인을 하면 결과 행 수는?
기준 쪽 행은 모두 남습니다. 부서코드가 NULL인 세 명도 부서 컬럼이 비어 있는 채로 남아 아홉 행입니다.
문제 7. 조인으로 표현된 질의를 서브쿼리로 바꾸어도 결과가 같아지는 경우로 가장 알맞은 것은?
존재 확인만 필요하면 조인 대신 EXISTS를 쓸 수 있고 행이 부푸는 문제도 피합니다. 자식 컬럼을 보여 줘야 한다면 조인이 필요합니다.
문제 8. 조인 결과에서 특정 테이블의 컬럼이 전부 NULL로 나타난다면 무엇을 뜻하나요?
외부 조인은 짝이 없으면 반대쪽 컬럼을 NULL로 채웁니다. 그것이 짝 없음의 표시입니다.
문제 9. 여러 테이블을 조인할 때 중간 결과가 커지지 않게 하려면 가장 먼저 할 일은?
읽는 양을 줄이는 것이 가장 큰 효과를 냅니다. 인덱스는 그다음 수단입니다.
문제 10. 다음 중 조인에 대한 설명으로 옳지 않은 것은?
행 수는 조건과 대응 관계가 정합니다. 합이 되는 것은 조인이 아니라 집합 연산자로 쌓았을 때입니다.

이전: 5강 ORDER BY 절 · 다음: 7강 표준 조인

모던지 · 궁금하면 모던지 GitHub · 2026-09-10