INNER JOIN

|

1. JOIN

 

JOIN이란, 두 개 이상의 테이블을 서로 묶어서 하나의 결과 집합으로 만들어 내는 것을 의미한다.

 

JOIN은 다음과 같이 네 가지 타입이 있다.

  • INNER JOIN
  • OUTER JOIN
  • CROSS JOIN
  • SELF JOIN

이번 챕터에서는 INNER JOIN에 대해서만 알아볼 것이다.

 

MSDN의 JOIN FUNDAMENTAL 페이지 Using JOINS 페이지를 참고하자.

 

 

2. INNER JOIN

 

대개의 업무에서 조인은 INNER JOIN을 주로 사용하며, 일반적으로 JOIN이라 하면, INNER JOIN을 지칭하는 것이다.

 

개념적인 이해를 돕기 위해, 우선 INNER JOIN을 사용해야 하는 경우에 대해 살펴보자.

아래 UserTable과 BuyTable을 기준으로 설명하겠다.

 

 

BuyTable을 보면, 물건을 구매한 사용자의 아이디와 물건 등의 정보만 나타난다.

그런데 이 물건을 배송하기 위해서는 구매한 회원의 주소를 알아야 한다.

이 회원의 주소를 알기 위해 주소 정보가 있는 UserTable과 결합하는 조인이 INNER JOIN이다.

 

우선 INNER JOIN의 기본 구문을 살펴보자.

 

SELECT <열 목록>

FROM <첫 번째 테이블>

    INNER JOIN <두 번째 테이블>

    ON <조인될 조건>

[WHERE 검색조건]

 

참고로, 위 형식에서 INNER JOIN을 JOIN이라고만 해도 INNER JOIN이라고 인식한다.

 

이제 BuyTable에서 'KJD'이라는 아이디를 가진 사람이 구매한 물건을 배송하기 위해서,

두 개의 테이블을 통째로 조인하려면 아래와 같이 하면 된다.

 

SELECT *

FROM BuyTable                         -- 첫번째 테이블

        INNER JOIN UserTable          -- 두번째 테이블

        ON BuyTable.ID = UserTable.ID -- JOIN 조건

WHERE BuyTable.ID = 'KJD'

 

위 예제의 결과는 다음과 같다.

 

 

UserTable과 BuyTable 모두 ID 컬럼이 존재하기에 반드시 테이블명.칼럼명 형태로 작성해야 한다.

그렇지 않으면, 아래와 같은 에러가 발생한다.

 

메시지 209, 수준 16, 상태 1, 줄 5

열 이름 'ID'이(가) 불확실합니다.

 

위 결과를 생성하기 위해서 다음과 같은 과정을 거친다.

  1. BuyTable의 'KJD' ID를 추출해 낸다.
  2. 'KJD'와 동일한 값을 UserTable에서 검색한 후
  3. 'KJD'라는 ID를 찾으면, BuyTable과 UserTable의 모든 칼럼을 결합(JOIN)한다.

만약, 위 예제에서 WHERE 문이 빠져 있다면, 모든 구매기록에 대해 BuyTable + UserTable의 결합이 발생하게 된다.

 

 

지금까지의 내용을 토대로 한 가지 사실을 유추해 낼 수 있다.

 

INNER JOIN 조인될 조건이 부합하는 행에 대해서만 JOIN이 발생하는 것이다.

 

 

3. 테이블의 별칭

 

이는 INNER JOIN에만 국한되는 것은 아니다.

다만, 앞으로 계속해서 사용하게 될 녀석이라 이 기회에 설명하고자 한다.

 

위 예제에서는 테이블 2개를 통째로 조인하였다.

그 결과 결합된 결과의 열이 너무 많아 이번엔 필요한 열만 추출해 보기로 하자.

 

SELECT BuyTable.ID, Name, GoodName, Addr, Mobile1 + N'-' + Mobile2 AS [연락처]

FROM BuyTable

        INNER JOIN UserTable

        ON BuyTable.Id = UserTable.ID

 

ID는 BuyTable에도 있고, UserTable에도 있기에 반드시 테이블명.컬럼명 형태로 작성해야 한다고 했다.

헌데, 매번 8~9 글자를 타이핑 하려니 여간 귀찮은 게 아니다.

 

이럴 때 테이블에 별칭을 부여하여, 타이핑을 간단하게 해 보자.

 

SELECT B.ID, Name, GoodName, Addr, Mobile1 + N'-' + Mobile2 AS [연락처]

FROM BuyTable AS B

        INNER JOIN UserTable AS U

        ON B.Id = U.ID

 

보통의 별칭 부여와 마찬가지로 AS 별칭을 구문을 사용하였다.

하지만, 테이블의 경우엔 간단히 FROM 절에 나오는 테이블 이름 뒤에 별칭만 붙여도 된다.

 

따라서, 위 예제에서 아래와 같이 테이블에 대해선 AS 를 생략할 수 있다.

 

SELECT B.ID, Name, GoodName, Addr, Mobile1 + N'-' + Mobile2 AS [연락처]

FROM BuyTable B

        INNER JOIN UserTable U

        ON B.Id = U.ID

 

 

4. DISTINCT를 이용한 예제

 

앞선 예제들에선 BuyTable에 UserTable을 결합시켰는데,

이번에는 반대로 UserTable에 BuyTable을 결합시켜 보자.

 

그리고 INNER JOIN은 조건에 부합되는 행만 조인하기에 이러한 특성을 이용하여,

한 번이라도 물건을 구매한 VIP 고객 정보만 추출해 보도록 하자.

 

-- DISTINCT문을 활용하여, 고객 명단만 추출하였다.

SELECT DISTINCT U.ID, Name, Addr

FROM UserTable U

        INNER JOIN BuyTable B

        ON U.ID = B.ID

 

위 예제를 EXISTS 구문을 이용하여 똑같은 결과를 얻을 수는 있지만,

이는 처리과정이 INNER JOIN에 비해 복잡하고 성능이 떨어지므로, 아래와 같은 방법은 혹여라도 사용하지 말자.

 

-- 아래 방법은 데이터베이스가 커질수록 성능이 나빠진다

SELECT DISTINCT U.ID, Name, Addr

FROM UserTable U

WHERE EXISTS

(

        SELECT *

        FROM BuyTable B

        WHERE U.ID = B.ID

)

 

 

5. 세 개 이상의 테이블 조인

 

테이블간 조인은 당연히 세 개 이상의 조인을 지원한다.

 

개념적으로 쉽게 접근하기 위해, 학생과 동아리의 관계를 생각해 보자.

한 학생은 여러 동아리에 가입할 수 있고, 한 동아리는 여러 학생이 가입할 수 있으므로, 

두 개는 서로 다대다(many-to-many) 관계라고 표현할 수 있다. 

 

다대다 관계를 구성하기 위해선 두 개의 테이블 사이에 연결 테이블을 둬서

이 연결 테이블과 두 테이블이 일대다 관계를 맺도록 구성해야 한다.

 

즉, 아래 세 테이블의 관계가 필요한 것이다.

 

-- 학생 테이블

-- 동명이인 처리를 위해 학생 이름을 PK로 잡진 않지만, 예제니까...

CREATE TABLE StudentTable

(

        Name NVARCHAR(5) NOT NULL PRIMARY KEY,

        Addr NVARCHAR(5) NOT NULL,

)

GO



-- 동아리 테이블

CREATE TABLE ClubTable

(

        Name NVARCHAR(5) NOT NULL PRIMARY KEY,

        RoomNo INT NOT NULL

)

GO



-- 학생과 동아리를 연결해주는 연결 테이블

-- 학생 테이블과 동아리 테이블의 PK들을 FK로 참조하고 있다

CREATE TABLE StdClubTable

(

        ID INT IDENTITY PRIMARY KEY,

        StdName NVARCHAR(5) NOT NULL FOREIGN KEY REFERENCES StudentTable(Name),

        ClubName NVARCHAR(5) NOT NULL FOREIGN KEY REFERENCES ClubTable(Name)

)

GO

 

위와 같이 테이블을 구성하고, 대략의 데이터를 채워 넣으면 아래와 같은 그림이 나온다.

 

 

이제 학생을 기준으로 학생이름, 지역, 가입한 동아리 이름, 동아리 방번호를 출력해 보자.

이를 출력하기 위해서는 다음과 같은 단계가 필요하다.

  1. StudentTable과 StdClubTable을 조인하여 학생 이름과 동아리 이름을 결합
  2. 이 결합된 것을 다시 ClubTable과 조인하여 동아리 방번호까지 결합

즉, 두 번의 조인(결합)이 필요하게 된다.

 

SELECT S.Name, Addr, C.Name, RoomNo

-- 먼저 StudentTable과 StdClubTable을 조인하고

FROM StudentTable S

        INNER JOIN StdClubTable SC

        ON S.Name = SC.StdName

            -- 그 결합에 다시 ClubTable을 조인한다

            INNER JOIN ClubTable C

            ON SC.ClubName = C.Name

 

위 예제의 결과는 다음과 같다.

 

 

And