SQL을 사용하다 보면 Join을 해서 테이블을 자주 합치게 됩니다. 데이터를 합칠 때 중복 값이 나올 수가 있습니다. DB를 관리할 때 보통 Join을 할때 대상이 유니크한 값을 가져야 합니다. 하지만 DB 관리를 잘못한 경우 중복이 발생할 수 있습니다. 이번에는 중복을 제거하는 방법에 대하여 알아보겠습니다. 다양한 방법들이 있으나 상황에 따라 사용하면 됩니다.
예시 테이블
T01 (사번, 이름, 직급, 휴대폰번호)
STAF_NO | STAF_NM | STAF_LEVEL | PHONE_NUM |
1000 | 홍길동 | 팀장 | 010-1234-1234 |
1001 | 김철수 | 대리 | 010-1234-1235 |
1002 | 김영희 | 대리 | 010-1234-1236 |
T02 (사번, 직급, 근속일자, 월급)
STAF_NO | STAF_LEVEL | STAF_DATE | STAF_MONEY |
1000 | 팀장 | 20100101 | 10000000 |
1001 | 대리 | 20120301 | 4000000 |
1001 | 대리 | 20120301 | 4000000 |
1002 | 대리 | 20190301 | 3000000 |
조인을 없애는 방법
우선 해당 테이블을 LEFT JOIN을 하는 경우 다음과 같은 결과가 나옵니다.
SELECT *
FROM T01
LEFT OUTER JOIN T02
ON T01.STAF_NO = T02.STAF_NO
AND T01.STAF_LEVEL = T02.STAF_LEVEL
STAF_NO | STAF_NM | STAF_LEVEL | PHONE_NUM | STAF_DAE | STAF_MONEY |
1000 | 홍길동 | 팀장 | 010-1234-1234 | 20100101 | 10000000 |
1001 | 김철수 | 대리 | 010-1234-1235 | 20120301 | 4000000 |
1001 | 김철수 | 대리 | 010-1234-1235 | 20120301 | 4000000 |
1002 | 김영희 | 대리 | 010-1234-1236 | 20190301 | 3000000 |
여기서 중복이 일어나는 이유가 무엇일까요? 위에서 설명한 것과 같이 DB를 관리할 때 보통 Join을 할 때 대상이 유니크한 값을 가져야 하는데 그렇지 않기 때문에 중복이 발생하였습니다. 중복을 해결하는 방법들을 한가지씩 나열하겠습니다.
0. 테이블 간 제약조건 확인
위에서 유니크한 값을 가져야 한다고 했는데 그렇지 않았기 때문에 중복이 일어났습니다. 만약 데이터가 아래 경우에는 어떨까요?
STAF_NO | STAF_LEVEL | STAF_DATE | STAF_MONEY |
1000 | 팀장 | 20100101 | 10000000 |
1001 | 대리 | 20120301 | 4000000 |
1002 | 대리 | 20190301 | 3000000 |
해당 값은 중복 없이 유니크한 값을 가지고 있기 때문에 데이터에 중복이 발생하지 않습니다. 우선 중복이 일어나는 근본적인 원인을 파악하는 가장 좋은 방법은 제약조건을 확인하는 방법입니다. 다음 방법부터는 만약에 제약조건이 보장되지 않았을 때 해결하는 방법을 하나씩 소개하려고 합니다.
1. DISTINCT
SELECT DISTINCT *
FROM T01
LEFT OUTER JOIN T02
ON T01.STAF_NO = T02.STAF_NO
AND T01.STAF_LEVEL = T02.STAF_LEVEL
STAF_NO | STAF_NM | STAF_LEVEL | PHONE_NUM | STAF_DAE | STAF_MONEY |
1000 | 홍길동 | 팀장 | 010-1234-1234 | 20100101 | 10000000 |
1001 | 김철수 | 대리 | 010-1234-1235 | 20120301 | 4000000 |
1002 | 김영희 | 대리 | 010-1234-1236 | 20190301 | 3000000 |
중복을 제거하는 가장 단순한 방법은 Distinct를 이용하는 방법입니다. 단 한 단어만 추가하기 때문에 간단하게 쿼리문을 작성할 수 있습니다. 하지만 Distinct는 전체 데이터를 temp tablespace에 저장하고 처리하는 방식이라 시스템에 과부하를 줄 수 있습니다.
2. GROUP BY
SELECT T01.STAF_NO, T01.STAF_NM, T01.STAF_LEVEL, T01.PHONE_NUM, T02.STAF_DATE, T02.STAF_MONEY
FROM T01
LEFT OUTER JOIN T02
ON T01.STAF_NO = T02.STAF_NO
AND T01.STAF_LEVEL = T02.STAF_LEVEL
GROUP BY T01.STAF_NO, T01.STAF_NM, T01.STAF_LEVEL, T01.PHONE_NUM, T02.STAF_DATE, T02.STAF_MONEY
두 번째 방법은 Group By로 묶는 방법입니다. Group By는 데이터를 특정하게 묶는 방법으로 데이터 중복을 제거할 때 Select 절의 칼럼과 Group By 절의 칼럼이 일치해야 합니다. Distinct에 비하여 조금 더 성능이 좋습니다. 대신 쿼리문이 많이 길어집니다.
3. Rank
SELECT T01.STAF_NO, T01.STAF_NM, T01.STAF_LEVEL, T01.PHONE_NUM, T02.STAF_DATE, T02.STAF_MONEY
FROM T01
LEFT OUTER JOIN (
SELECT STAF_NO, STAF_LEVEL, STAF_DATE, STAF_MONEY,
RANK() OVER (PARTITION BY STAF_NO, STAF_LEVEL ORDER BY STAF_DATE) AS STAF_RANK
FROM T02
) T02
ON T01.STAF_NO = T02.STAF_NO
AND T01.STAF_LEVEL = T02.STAF_LEVEL
WHERE T02.STAF_RANK = 1
마지막으로 RANK 함수를 이용하는 방법입니다. RANK 함수를 통하여 순위를 선정하게 됩니다. 순위의 기준을 JOIN으로 묶는 값을 두는 경우 중복된 값은 1위 2위 등 여러 순위를 가지게 됩니다. 그중 1위만 출력되게 하면 자연스럽게 중복이 제거됩니다.
'컴퓨터 > MySQL' 카테고리의 다른 글
MySQL (18) - 트리거(Trigger)를 만들어보자 (0) | 2024.03.07 |
---|---|
MySQL (16) - 뷰(View)에 대하여 알아보자 (0) | 2023.10.03 |
MySQL (15) - 쿼리문을 합하는 방법 (UNION, UNION ALL) (0) | 2023.08.13 |
MySQL (14) - 내장함수를 이용하여 날짜 및 시간을 다뤄보자 (0) | 2023.06.20 |
MySQL (13) - 프로시저(Procedure)와 함수(Function) (0) | 2023.05.01 |