Search

7-4. 관계선 없이 조인 컬럼 추리하기

ERD에 관계선이 없다면?

안타깝게도 일부 개발 현장에는 ERD 자체가 없거나 ERD가 있어도 관계선이 그려지지 않은 경우가 많다. 데이터를 제대로 활용하려면 ERD 부터 제대로 체계를 갖고 관리할 필요가 있다. 어쨋든 ERD는 있으나 관계선이 없다면, 한 테이블의 PK 컬럼이 다른 테이블에서 어떻게 사용되는지 관찰해 조인 컬럼을 유추해야 한다.
A 테이블의 PK가 그대로 B 테이블에 존재
만약에 A 테이블의 PK와 B 테이블의 PK가 동일하다면 둘은 1:1 관계다.
PK 컬럼을 사용해 두 테이블을 조인하면 된다.
A 테이블의 PK가 B 테이블에 존재
이때, A 테이블의 PK와 B 테이블의 PK는 완전히 같지 않다.
그리고 A 테이블의 PK는 B 테이블에서 PK의 일부이거나 일반 컬럼일 수도 있다.
A:B = 1:M의 관계일 가능성이 높고, A 테이블의 PK 컬럼을 사용해 조인을 처리하면 된다.
A 테이블의 PK 컬럼이 여러 개라면, 해당 컬럼이 모두 B 테이블에 있어야 두 테이블을 조인할 수 있다.
아래 ERD는 가상의 넷플릭스 데이터베이스를 설계해 본 것이다. ERD를 보고 조인 가능한 관계들을 찾아보자. 빨간색은 단독 컬럼으로 PK가 만들어진 경우, 파란색은 두 개 이상의 컬럼이 PK를 구성한 경우다.
이와 같은 추측은 경우에 따라 틀릴 수 있다. ERD에 관계선도 없고 업무에 대한 지식도 부족한 상태에서 100% 정확하게 관계를 파악하는 것은 불가능하다. 다만, 관계선과 업무 지식이 없는 상황에서는 최선의 방법일 수 있으면 이 방법을 시작으로 테이블 간의 관계를 하나씩 파악해 나가면 된다.

ERD 조차 없다면?

가끔 “ERD가 없는데 어떻게 하면 좋을까요?” 라는 질문을 받는다. 이때 한결같은 대답은 “직접 그려 보세요. 생각보다 어렵지 않습니다.” 이다. 개인차에 따라 힘들수도 있으며, 그리기에 부담될만큼 너무 많은 테이블이 있을 수도 있다. 그렇다면 중요 테이블 몇 개만 우선 그려보기 바란다. 테이블 간의 관계 파악도 어렵다면, PK만이라도 그려보기 바란다. ERD를 만들어가다 보면 생각보다 쉽게 테이블 간의 조인 컬럼을 찾아 낼 수 있다.

조인 조건에는 어느 한쪽 테이블의 PK가 참여

앞에서 “일반적으로 조인은 관계가 있는 테이블 간에, 관계 컬럼(PK/FK)을 통해 이루어진다. “라고 설명했다. 이 말은 두 테이블이 조인할 때, “조인 조건에는 어느 한쪽 테이블의 PK가 반드시 참여”한다는 뜻이기도 하다. STARTDB의 테이블 간 조인 SQL을 간단하게 살펴보자. 조인 조건에 사용되는 컬럼이 어느 한쪽의 PK라는 것을 알 수 있다.
-- [SQL-7-4-1] -- Shop의 PK인 ShopId가 조인 조건으로 사용 -- Ord에서 ShopId는 FK(Foreing Key) SELECT T1.* ,T2.* FROM startdb.Shop T1 INNER JOIN startdb.Ord T2 ON (T1.ShopId = T2.ShopId) LIMIT 10; -- [SQL-7-4-2] -- Member의 PK인 MemberId가 조인 조건으로 사용 -- Ord에서 MemberId는 FK SELECT T1.* ,T2.* FROM startdb.Member T1 INNER JOIN startdb.Ord T2 ON (T1.MemberId = T2.MemberId) LIMIT 10; -- [SQL-7-4-3] -- Ord의 PK인 OrdNo가 조인 조건으로 사용 -- OrdDet에서 OrdNo는 FK이면서 PK(OrdNo,OrdDetNo)의 일부 SELECT T1.* ,T2.* FROM startdb.Ord T1 INNER JOIN startdb.OrdDet T2 ON (T1.OrdNo = T2.OrdNo) LIMIT 10; -- [SQL-7-4-4] -- Item의 PK인 ItemId가 조인 조건으로 사용 -- OrdDet에서 ItemId는 FK SELECT T1.* ,T2.* FROM startdb.OrdDet T1 INNER JOIN startdb.Item T2 ON (T1.ItemId = T2.ItemId) LIMIT 10;
SQL
복사
모든 조인 조건에 어느 한쪽 테이블의 PK가 반드시 참여하는 것을 알 수 있다. 그리고 그 PK 컬럼들은 반대쪽 테이블에 존재하고 있다. 해당 컬럼에 대해 FK 제약을 만들었다면 FK 컬럼으로 설정되어 있을 것이다.
Tip. FOREIGN KEY 일반적으로 FK는 DBMS 내에 FOREIGN KEY라는 제약을 만들어 구성한다. 그렇다고 조인을 위해 FK를 만들어야 하는 것은 아니며, 실제 FK는 생략하는 경우가 많다. 개인적으로 주요 마스터 테이블들은 FK를 만드는 것이 좋으며, 대량의 발생(트랜잭션) 테이블에는 FK를 만들지에 대한 고민이 필요하다고 생각한다.
Tip. 무조건 PK만 조인할 수 있는가? 조인을 쉽게 이해시키기 위해 PK/FK 간에 조인이 이루어진다고 계속해서 설명했다. 하지만 DBMS는 조인 조건만 맞아 떨어지면 데이터를 연결시켜준다. PK/FK 간에만 조인을 할 수 있는 것이 아니다. 서로 PK/FK가 아니어도 연결할 필요성이 있다면 언제든지 조인으로 처리할 수 있다. 단, 제대로 된 조인 결과를 만들기 위해서, 조인 컬럼을 적절하게 선택해야 한다. 이때, 어떤 컬럼으로 조인했을 때 데이터 집합이 어떻게 변형되는지 잘 알고 있어야 한다.
다른 테이블을 통해 조인 조건 컬럼을 선정하는 연습을 해보자. 아래 내용을 꼭 기억하고 조인 조건을 작성해야 한다.
조인 할 때 어느 한쪽 테이블의 PK가 여러개라면 하나도 빠지지 않고 조인 조건에 사용되어야 한다.
아래는 회원요금결제와 회원요금결제상세 테이블이다. 회원요금결제는 PK가 (회원ID)와 (요금결제월) 두 개로 구성되어 있다. 회원요금결제상세는 (회원ID), (회원요금결제월), (요금결제순번) 세 개로 구성되어 있다. 두 테이블 간에 관계선도 없고 실제 FK 제약도 없지만, 테이블명과 컬럼명그리고 PK 구성을 통해 회원요금결제상세는 회원요금결제를 참조한다고 추측할 수 있다.
두 테이블은 회원요금결제 테이블의 PK인 (회원ID)와 (요금결제월) 두 컬럼을 이용해 조인을 처리해야 한다. 그래야만 아래 그림과 같이 정상적인 1:M 조인이 이루어진다.
이번에는 두 테이블을 (회원ID)만 사용해 조인을 한다고 가정해보자. 아래 그림과 같이 M:M 처럼 조인이 이루어진다. 회원요금결제 데이터 한 건이 회원요금결제상세의 여러 건과 조인이 된다. 그리고 회원요금결제상세의 한 건도 회원요금결제 여러 건과 조인이 된다. 아래 그림에서 조인 전 데이터를 살펴보면, M1 회원의 2024년 1월의 요금결제상세 건수는 한 건이다. 그러나 회원ID로 조인한 후에 M1 회원의 2024년 1월의 요금결제 상세 건 수는 세 건이 되어 버린다. 이처럼 조인 조건의 컬럼이 누락되면 의도치 않은 중복 데이터가 만들어지고 이로 인해 데이터 분석이나 집계 처리에 문제가 발생된다.
어느 한쪽 테이블의 PK가 조인 조건 컬럼으로 모두 사용되어야 한다. PK라고 강조했지만 반드시 PK일 필요는 없다. 정확히는 데이터 집합의 레코드를 식별할 수 있는 Key면 된다. PK는 Key 중에 대표 Key이고 우리가 이해하기 쉽기 때문에 PK로 설명을 한 것이다.
Upper: 7. JOIN