Search

7-6. JOIN과 데이터 집합

JOIN과 데이터 집합

조인을 테이블과 테이블이 아닌 데이터 집합과 데이터 집합 간의 연결로 생각할 필요가 있다. 아래 그림은 A 테이블, B 테이블, C 테이블이 조인하는 과정이다.
위 그림을 설명하면,
테이블 A, 테이블 B, 테이블 C를 조인
테이블 A와 테이블 B 조인 → 데이터 집합 AB가 만들어진다.
조인을 통해 만들어진 AB는 물리적인 테이블이 아니므로 데이터 집합으로 해석
데이터 집합 AB와 테이블 C 조인 → 데이터 집합 ABC(최종결과)가 만들어진다.
테이블 A, 테이블 B, 테이블 C를 데이터집합 A, 데이터집합 B, 데이터집합 C 로 생각하자.
데이터 집합 A와 데이터 집합 B 조인 → 데이터 집합 AB가 만들어진다.
데이터 집합 AB와 데이터 집합 C 조인 → 데이터 집합 ABC(최종결과)가 만들어진다.
이처럼 SQL 세계에서는 테이블을 데이터 집합으로 생각해도 전혀 이상이 없다. 테이블보다는 데이터 집합이라는 생각을 갖기 바란다.

JOIN은 한 번에 두 개의 데이터 집합만

이제 여러 테이블(데이터 집합)을 조인하기 위해 준비할 차례다. 걱정할 필요 없다. 한 문장의 SQL에서 여러 테이블이 조인 될 때는, 한 순 간에는 두 개의 데이터 집합만 조인에 참여한다고 생각하자. DB 내부적으로 어떻게 처리하는지는 중요하지 않다. 개념적으로 한 번에 두 데이터 집합만 조인할 수 있다고 생각하고 SQL을 작성하자.
아래 그림을 살펴보자. 세 개의 데이터 집합을 조인한다면 그림의 왼쪽과 같이 두 개의 데이터 집합이 조인해 하나의 데이터 집합이 만들어지고, 나머지 하나의 데이터 집합과 조인이 이루어진다. 오른쪽과 같이 세 데이터 집합이 동시에 조인 된다고 생각하지 말자.
위 그림의 왼쪽과 같이 한 순간에는 두 데이터 집합만 연결된다는 개념을 가지고 SQL을 작성하기 바란다.
회원(Member)과 주문(Ord), 그리고 주문상세(OrdDet)를 조인해보자. 조인에 앞서 세 테이블의 구조를 살펴보면 다음과 같다.
테이블 구조를 통해 테이블 간 조인 조건 컬럼을 먼저 정리해보자.
Member와 Ord: Member의 PK인 MemberId가 조인 컬럼이다.
Ord와 OrdDet: Ord의 PK인 OrdNo가 조인 컬럼이다.
이제 조인 SQL을 작성해보자. 단, 세개 테이블을 조인하는 SQL을 한 번에 완성하려고 하지 말자, 단계적으로 작성하고 실행해 결과를 중간 중간 확인하면서 SQL을 완성하기 바란다.
-- [SQL-7-6-1] -- 1. Member와 Ord를 먼저 조인하자. -- NickNm이 Air이면서, 주문일시는 2023년 1월 1일인 주문만 조인할 것이다. SELECT T1.MemberId ,T1.NickNm ,T2.OrdNo ,T2.OrdDtm FROM startdb.Member T1 INNER JOIN startdb.Ord T2 ON (T2.MemberId = T1.MemberId) WHERE T1.NickNm = 'Air' AND T2.OrdDtm >= STR_TO_DATE('20230101','%Y%m%d') AND T2.OrdDtm < STR_TO_DATE('20230104','%Y%m%d'); MemberId NickNm OrdNo OrdDtm -------- ------ ----- ------------------- M0001 Air 67277 2023-01-01 08:00:00 M0001 Air 67286 2023-01-02 08:00:00 M0001 Air 67586 2023-01-03 08:00:00 -- [SQL-7-6-2] -- 2. 위 데이터집합에 OrdDet를 조인하자. -- Ord와 OrdDet의 조인 컬럼은 OrdNo다. 그러므로 OrdNo를 사용해 조인을 해야 한다. -- 조인컬럼으로 Ord 테이블의 OrdNo를 사용하지만, -- Ord와 OrdDet의 조인이 아니라, -- (Member와 Ord의 조인 결과 집합)에 OrdDet를 조인한다고 생각하자. SELECT T1.MemberId ,T1.NickNm ,T2.OrdNo ,T2.OrdDtm ,T3.ItemId ,T3.OrdQty FROM startdb.Member T1 INNER JOIN startdb.Ord T2 ON (T2.MemberId = T1.MemberId) INNER JOIN startdb.OrdDet T3 ON (T3.OrdNo = T2.OrdNo) WHERE T1.NickNm = 'Air' AND T2.OrdDtm >= STR_TO_DATE('20230101','%Y%m%d') AND T2.OrdDtm < STR_TO_DATE('20230104','%Y%m%d'); MemberId NickNm OrdNo OrdDtm ItemId OrdQty -------- ------ ----- ------------------- ------ ------ M0001 Air 67277 2023-01-01 08:00:00 HCHB 1 M0001 Air 67286 2023-01-02 08:00:00 BGLR 1 M0001 Air 67586 2023-01-03 08:00:00 HCHR 1
SQL
복사
세 테이블의 조인 과정을 논리적으로 그려보면 아래와 같다.
위 과정을 말로 풀어보면 다음과 같다.
Member에서 NickNm이 Air인 데이터를 가져와 T1 데이터 집합 생성
Ord에서 OrdDtm이 2023년 1월 1일~2023년 1월 3일인 데이터를 가져와 T2 데이터 집합 생성
T1과 T2 데이터 집합을 조인해 T1T2라는 새로운 데이터집합 생성
T1T2 데이터집합과 OrdDet(T3) 데이터집합을 조인
Ord와 OrdDet를 조인하는 것이 아니라,
Member와 Ord의 조인으로 얻은 새로운 데이터 집합과 OrdDet를 조인하는 것이다.
실제 DBMS 내부적으로 이렇게 처리된다고 말할 수는 없다. 하지만 우리가 조인을 작성할 때는 이 처럼 한 번에 두 개씩만 조인된다고 생각하며 조인을 작성하면, 비교적 쉽게 많은 테이블의 조인도 해낼 수 있다. 그리고 이러한 과정이 익숙해지면 많은 테이블을 단숨에 조인하는 것도 전혀 어렵지 않게 될 것이다.

JOIN 순서는 상관 없다.

여러 데이터 집합(테이블)을 조인할 때, 데이터 집합의 조인 순서는 결과에 영향을 주지 않는다. 아래는 네 개의 데이터 집합을 조인하는 예다. 어떤 순서로 조인하든 결과는 ABCD로 같다.
여러 테이블의 조인을 작성할 때, 조인할 테이블들의 순서보다는 조인할 두 데이터 집합 간에 조인 컬럼이 정확한가에 대해 중점을 두기 바란다.
Upper: 7. JOIN