- 조인이란 연관관계가 있는 여러 테이블들을 하나로 연결해 마치 하나의 테이블인 것처럼 보여주는 기능이다.
- 보통은 pk - fk 를 이용해 두 테이블을 연결하여 데이터를 수평적으로 확장할수 있다.
- 물론 테이블 하나에 모든 정보를 담는다면 조인이 필요없겠지만, 이런 방식은 아래와 같은 문제가 있다.
- 각 행별로 데이터가 중복될 수 있다. 만약 주문정보를 유저 정보와 함께 저장한다면 각 주문정보별로 유저 정보가 같이 포함되어 똑같은 유저 정보가 여러개 존재할 수 있다. 이렇게 되면 공간이 많이 낭비될 수 밖에 없다.
- 만약 유저의 정보가 변경되면 모든 행을 뒤져서 해당 유저의 정보가 담긴 행들을 찾고 수정해야 한다. 만약 특정 행이 수정되지 않았다면 해당 데이터를 가져왔을 때 수정되지 않은 유저 정보가 보일수도 있다.
- 만약 새로운 유저를 추가하고 싶은데 주문 정보와 함께 저장해야 한다면 새로운 유저는 주문을 한번이라도 해야 저장될 수 있는 이상한 상황이 발생한다.
- 만약 주문정보를 지우려고 할 때 유저 정보도 같이 있다면 쉽게 지울 수 없다. 주문정보를 지우는 순간 유저 정보도 날라갈 수 있기 때문이다.
- 이런 이유들때문에 정규화 라는 것을 거치며 중복을 최대한 제거하며, 간단히 말해 유저 정보는 users 테이블에, 주문 정보는 orders 테이블에 두고 두 테이블을 fk로 연결하는 것이다.
- 이런식으로 정규화 된 테이블들이 있을 때 실제로 사용자가 조회할때는 주문 정보 + 유저 정보 까지 필요할 수 있다. 이런 경우 join을 사용해 두 테이블을 합쳐서 보여줄 수 있는 것이다.
내부 조인 기본
- 내부 조인이란 두 테이블 모두에 존재하는 데이터만 골라서 보여주는 조인이다.
- 예를 들어 orders 테이블의 user_id 로 users 의 id 와 조인한다면
- orders의 데이터 중 user_id가 users 테이블에 존재하는 데이터만 포함된다.
- 만약 orders의 데이터 중 user_id가 null 이거나, users 테이블에 존재하지 않는 경우에는 포함되지 않는다.
SELECT * FROM orders INNER JOIN users ON orders.user_id = users.user_id;
-- 제일 기본적인 문법으로, orders 테이블의 데이터를 가져오면서 연결된 users의 데이터도 같이 가져온다.
-- 예를 들어 orders 에 order_id, user_id, order_date 이 있고 users에 user_id, name 이 있다면
-- 최종 결과는 (order_id, user_id, order_date, user_id, name) 가 컬럼으로 나오게 된다.
-- 이 경우 user_id 가 중복되기도 하고, 컬럼이 엄청나게 많아질 수 있기 때문에 직접 가져올 컬럼을 지정하는 게 좋다.
SELECT o.order_id, u.user_id, o.order_date FROM orders o JOIN users u ON o.user_id = u.user_id;
-- 제일 많이 쓰는 형식으로, ON절을 쓰기 편하게 테이블의 별칭을 적고, INNER 도 생략했다.
-- 단순히 JOIN 이라고 쓰면 기본적으로 내부조인이므로 생략할 수 있다.
-- 지금은 SELECT에서 별칭은 사용하지 않았지만, 중복되는 컬럼 이름이 있다면 별칭을 정하는게 좋다.
SELECT
o.order_id,
u.user_id
FROM
orders o
JOIN users u ON o.user_id = u.user_id
WHERE
o.order_date > '2025-06-01';
SELECT
o.order_id,
u.user_id
FROM
orders o
JOIN users u ON o.user_id = u.user_id
WHERE
u.age > 20;
-- 이런식으로 WHERE 절도 똑같이 사용 가능하다.
내부 조인 주의사항
- 조인의 ON 조건은 WHERE절과 다르게 두 테이블을 연결할 기준이다.
- 이 기준으로 일반 컬럼도 가능하지만, 중복이 발생하거나 일관성이 없을수도 있어서 제대로된 결과가 나오지 않을 수 있다.
- 그래서 pk - fk 로 하면 일관적이고 확실하게 결과가 나오기 때문에 이 조건을 주로 사용한다.
- JOIN 의 결과는 1대1이 아닐수도 있다. 예를 들어 users 테이블 기준으로 orders 테이블을 조인하면
- 각 유저별 주문 데이터가 모두 나오기 때문에 1:N 관계처럼 데이터가 나올수도 있다.
- 내부조인은 어떤 테이블을 기준으로 JOIN을 해도 결과가 같다.
- 위 쿼리에서 FROM orders, FROM users 처럼 기준이 되는 테이블이 달라도 어짜피 교집합이기 때문에 결과가 같다.
- 하지만 외부조인의 경우에는 결과가 많이 달라지므로 주의해야 한다.
- ORDER BY 같은 정렬도 똑같이 사용할 수 있고, GROUP BY 도 가능하다.