개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

기초개념 › DB

조인

조인은 무엇을 이어 붙이고, ON은 무엇을 정하는가

조인은 두 테이블의 행을 옆으로 이어 붙이는 SELECT입니다. 이 실습의 orders 테이블에는 주문한 회원의 번호(member_id)만 적혀 있고 이름은 member 테이블에 있어서, 주문한 물건과 주문한 사람의 이름을 함께 보려면 두 테이블을 이어야 합니다. JOIN member m은 이어 붙일 테이블을 정하고, ON o.member_id = m.id는 "어떤 행끼리 짝인지"를 정합니다. DB는 주문 행마다 ON 조건이 맞는 회원 행을 찾아 한 줄로 붙입니다. 이 실습은 JOIN을 지우거나 ON 조건을 없애고, 짝이 없는 주문을 넣어 가며 같은 SQL을 실행해, 결과가 몇 줄이고 어떤 모양인지를 봅니다.

실행으로 대조 · H2 2.4.240에서 여섯 가지 조합을 실행해 대조, 규칙은 MySQL 문서와 대조

이 실습에 나오는 개념

JOIN (INNER, OUTER)
두 테이블의 행을 조건에 따라 결합하는 연산이다. INNER JOIN은 양쪽에서 조건이 맞는 행만 결과에 포함한다. LEFT OUTER JOIN은 왼쪽 테이블의 모든 행을 포함하고 오른쪽에 짝이 없으면 NULL로 채운다. 짝이 없는 데이터도 결과에 남겨야 하는지에 따라 선택한다.
ON 조건
JOIN으로 두 테이블을 이을 때, 어떤 행끼리 짝인지를 정하는 조건이다. JOIN member m ON o.member_id = m.id처럼 JOIN 뒤에 ON을 쓰고 조건식을 적으면, DB는 이 조건이 참이 되는 두 행을 짝으로 보고 한 줄로 붙인다. 조건식은 WHERE에 쓸 수 있는 것과 같은 모양이며, 보통 ON은 테이블을 어떻게 이을지를, WHERE는 결과에 넣을 행을 고르는 데 쓴다. ON에는 보통 그 JOIN이 잇는 두 테이블의 열을 견주는 조건을 적는다. MySQL에서는 ON이 없는 JOIN이 CROSS JOIN처럼 동작하고, 이때는 짝을 가리지 않고 모든 행을 모든 행과 붙인다.
테이블 별칭
FROM 절에서 테이블에 붙이는 짧은 다른 이름이다. FROM orders o처럼 테이블 이름 뒤에 적거나 FROM orders AS o처럼 AS를 넣어 적으며, 두 방식은 같은 뜻이다. 별칭을 붙이면 SELECT나 ON에서 o.item, m.name처럼 "어느 테이블의 열인지"를 짧게 밝힐 수 있다. 두 테이블이 같은 이름의 열(예: id)을 가질 때는 별칭으로 어느 쪽인지 밝혀야 하는 경우가 많다. 컬럼 별칭(AS)은 열에 붙이는 이름이고, 테이블 별칭은 테이블에 붙이는 이름이다.
카테시안 곱
두 집합의 모든 조합을 만들어 내는 것이다. SQL에서 한 엔티티에 딸린 두 개의 컬렉션을 동시에 조인하면 결과 행 수가 두 컬렉션 크기의 곱으로 늘어난다. 불필요하게 많은 데이터가 전송되고 메모리를 차지하므로 여러 컬렉션을 한 번에 조인해 가져오는 것은 피한다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. CREATE TABLE과 INSERT: DB가 member와 orders 두 테이블을 만들고 행을 넣습니다. member에는 회원 2명(id 1 김철수, id 2 이영희)이 있고, orders에는 주문 3개(10번 키보드, 11번 마우스, 12번 모니터)가 있습니다. orders에는 누가 주문했는지가 member_id 열의 번호로만 적혀 있습니다(주문 10의 member_id는 1). 그 번호에 해당하는 이름은 member 테이블에만 있습니다.
  2. SELECT o.item, m.name FROM orders o JOIN member m ON o.member_id = m.id: 주문한 물건과 회원의 이름을 함께 읽는 SELECT입니다. FROM orders o는 orders 테이블을 읽는다는 뜻(o는 orders의 짧은 이름)이고, JOIN member m은 member 테이블(m은 member의 짧은 이름)을 이어 붙인다는 뜻이며, ON o.member_id = m.id는 주문 행의 member_id와 회원 행의 id가 같은 행끼리 짝이라는 뜻입니다. 결과가 만들어지는 원리를 순서대로 풀어 쓰면, DB가 orders의 행마다 ON 조건에 맞는 member의 행을 찾아 옆으로 붙입니다. 실제로 DB가 어느 테이블부터 어떤 방법으로 찾는지는 DB가 정합니다.
  3. DB가 orders에서 먼저 주문 10 행(member_id 1, 키보드)을 봅니다. ON 조건 o.member_id = m.id에 맞는 member의 행을 찾습니다. 이 주문의 member_id가 1이므로 id가 1인 행, 김철수 행이 짝입니다.
  4. DB가 주문 10 행과 김철수 행을 옆으로 붙입니다. 붙인 행에서 SELECT에 적은 o.item(키보드)과 m.name(김철수)을 꺼내 "키보드, 김철수" 한 줄을 결과에 넣습니다. orders에는 없던 이름이 같은 줄에 나왔습니다. 이것이 조인입니다.
  5. DB가 주문 11 행(member_id 1, 마우스)의 짝으로 id가 1인 김철수 행을 찾아 붙이고, "마우스, 김철수" 한 줄을 결과에 넣습니다. 앞의 주문에도 같은 김철수 행이 붙었습니다. 회원 한 행이 여러 주문에 붙을 수 있습니다.
  6. DB가 주문 12 행(member_id 2, 모니터)의 짝으로 id가 2인 이영희 행을 찾아 붙이고, "모니터, 이영희" 한 줄을 결과에 넣습니다.
  7. SELECT의 결과: orders의 행을 모두 보았습니다. 결과는 3행입니다. 주문 3개마다 한 줄씩 만들어졌습니다.

실행 결과

코드

CREATE TABLE member (id INT PRIMARY KEY, name VARCHAR(20));
CREATE TABLE orders (id INT PRIMARY KEY, member_id INT, item VARCHAR(20));
INSERT INTO member VALUES (1, '김철수'), (2, '이영희');
INSERT INTO orders VALUES (10, 1, '키보드'), (11, 1, '마우스'),
    (12, 2, '모니터');

-- 조인: orders의 행에 member의 행을 옆으로 붙인다
SELECT o.item, m.name
FROM orders o
-- ON: member_id가 회원의 id와 같은 행끼리 짝이다
JOIN member m ON o.member_id = m.id
ORDER BY o.id;

이 모형의 전제

H2 2.4.240(메모리 DB, JDBC)에서 실행해 대조했습니다. 여섯 가지 조합을 모두, 화면의 SQL 전체(주석 줄 포함)를 글자 그대로 문장 하나씩 실행해서, SELECT가 돌려준 행 수와 모든 행의 값(item과 name 또는 member_id)을 모형과 대조했습니다. 결과가 네 행을 넘으면 앞의 네 행과 모두 몇 행인지로 줄여 적었고, 대조할 때도 같은 규칙을 썼습니다. 이 밖에 단계 문장이 기대는 값도 H2에서 따로 확인했습니다: orders의 행 수, member에 id가 9인 회원이 없다는 것, 짝이 되는 회원의 id, 그리고 ON 없는 CROSS JOIN의 행 수가 두 테이블의 행 수를 곱한 수라는 것입니다. 정의와 규칙은 MySQL 8.4 문서를 열어 확인했습니다. 15.2.13.2절 JOIN Clause에서 MySQL은 JOIN, CROSS JOIN, INNER JOIN을 서로 바꿔 쓸 수 있는 같은 것으로 보고(표준 SQL은 ON이 있으면 INNER JOIN, 없으면 CROSS JOIN), 조건이 없으면 두 테이블의 카테시안 곱이 만들어지며, ON 조건은 WHERE에 쓸 수 있는 조건식이고 보통 테이블을 어떻게 이을지를 정하는 데 쓴다고 합니다. 테이블 별칭은 같은 절과 15.2.13절 SELECT 문의 FROM 설명(tbl_name AS alias_name 또는 tbl_name alias_name)을 따랐습니다. 다만 두 문서는 짝이 없는 행이 INNER JOIN 결과에 나오지 않는다고 따로 적어 두지는 않아서, 이 동작은 H2의 실행으로 확인한 것입니다. 문서는 웹 페이지를 요약해 주는 도구로 열었고 원문을 한 글자씩 확인한 것은 아닙니다. MySQL에서의 실행 대조는 하지 않았습니다. 단계 문장은 결과가 만들어지는 원리를 순서대로 풀어 쓴 것입니다. 실제로 DB가 어느 테이블부터 읽고 어떤 방법으로 짝을 찾는지는 DB가 정하며, 결과의 줄 순서는 화면의 ORDER BY가 정합니다. 짝이 없는 행도 남기는 LEFT JOIN은 다루지 않으며, 공부 쪽 실습 "JOIN과 GROUP BY"에서 다룹니다.

앞 실습: WHERE · 다음 실습: GROUP BY와 집계

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요