일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 1
- autowired
- 오토와이어드
- layout #thymeleaf #화면분할
- 스프링 부트
- Component
- spring
- git #gitlab #github
- DispatcherServlet
- zepettoworld.com
- 스프링
- Bean
- Today
- Total
기록과 정리
SQL-JOIN 본문
이 글은 '[백문이불여일타] 데이터 분석을 위한 중급 SQL' 강의를 참고하였습니다.
소개
Join은 두개 이상의 테이블을 합쳐서 봐야하는 경우 사용하는 SQL 문법이다.
아래 테이블은 이번 글에서 사용할 예시 테이블 ( Users, Orders ) 이다.
Users
ID | 로그인 아이디 | 주소 |
1 | A | 강서구 방화동 |
2 | B | 금천구 시흥동 |
3 | C | 강남구 삼성동 |
Orders
userId | 구매상품 | 가격 | 결재수단 |
1 | 안경 | 20000 | 우리카드 |
2 | 마우스 | 100000 | 국민카드 |
3 | 선풍기 | 50000 | 계좌이체 |
INNER JOIN
Id | 로그인 아이디 | 주소 | userId | 구매상품 | 가격 | 결제수단 |
1 | A | 강서구 방화동 | 1 | 안경 | 20000 | 우리카드 |
2 | B | 금천구 시흥동 | 2 | 마우스 | 100000 | 국민카드 |
3 | C | 강남구 삼성동 | 3 | 선풍기 | 50000 | 계좌이체 |
이전에는
SELECT *
FROM Users, Orders
WHERE Users.Id = Orders.userId
와 같이 테이블을 두개를 같이 조회를 하여 ( 카티션 프로덕트 : 각 행의 모든 경우의 수를 가져옴 ) 조건을 거는 쿼리를 취했다면 요새는 위와 같은 쿼리를 이용한다고 보면 된다.
좋은 조회시 쿼리는
SELECT *
FROM Users
INNER JOIN Orders On Users.Id = Orders.userId
예약어(INNER JOIN)을 사용해주는 것이 더 명확하다. INNER JOIN은 양쪽 테이블에 데이터가 다 있을 경우, 조회할 수 있다.
예를 들어 Orders에 'userId = 3'인 데이터가 없다고하면 두 테이블을 조인시 3번째 row는 나오지 않게 된다. 집합으로 치면 교집합으로 볼 수도 있다.
JOIN은 종류가 많기때문에 각 조인마다 벤다이어그램을 사용하여 이해하기 쉽게 도와주는 사이트가 있다. 해당 조인 영역에 따라 쿼리도 출력 가능하다.
https://sql-joins.leopard.in.ua/
join key로 사용되는 컬럼들간에 이름이 다른 경우는 얼마든지 생길 수 있다. 이럴 경우, ERD를 분석해서 어떤 관계를 가지고 있는지 ( 1대다 , 1대1 등) 분석하여 파악하도록 하자.
OUTER JOIN (LEFT, RIGHT)
INNER JOIN을 제외하고 나머지는 다 OUTER JOIN 이라고 생각하면된다. 그럼 OUTER JOIN은 무엇인지, 왜 필요한지 알아보자.
LEFT JOIN
Orders
userId | 구매 상품 | 가격 | 결제수단 |
1 | 안경 | 20000 | 우리카드 |
2 | 마우스 | 100000 | 국민카드 |
위에 예시를 들었던 Oders 테이블에 3번째 로우가 없어졌다. 여기서 LEFT 조인을 하게 되면
Id | 로그인 아이디 | 주소 | userId | 구매상품 | 가격 | 결제수단 |
1 | A | 강서구 방화동 | 1 | 안경 | 20000 | 우리카드 |
2 | B | 금천구 시흥동 | 2 | 마우스 | 100000 | 국민카드 |
3 | C | 강남구 삼성동 | NULL | NULL | NULL | NULL |
query)
SELECT *
FROM Users
LEFT JOIN Orders ON Users.Id = Orders. userId
Users(왼쪽) 기준으로 데이터를 전부 뽑고 싶다고 하면 , 다음과 같이 출력을 할 수 있고 Orders(오른쪽)에 데이터가 없는 구간은 NULL로 출력이 된다. INNER JOIN시에 Orders 레코드가 있는 경우, 즉 한번이라도 주문을 한사람들만 출력이 가능하다. LEFT JOIN의 경우, Users 기준으로 모두 출력한 경우라고 할 수 있다.
SELECT *
FROM Users
LEFT JOIN Orders ON Users.Id = Orders. userId
WHERE OrderId IS NULL
을 해준다면 한번도 주문을 하지 않은 데이터를 가져올 수도 있다.
RIGHT JOIN의 경우는 반대의 경우라고 볼 수 있다. 보기에도 좋은 이유로 LEFT join으로 해결하는 경우가 많다.
Full Outer Join의 경우 , LEFT + RIGHT OUTER 조인으로 볼 수있는데 MySQL에서는 지원하지 않기 때문에 LEFT JOIN 과 RIGHT JOIN을 UNION 하여 사용하면된다.
SELF JOIN
자기 테이블을 자기에게 조인을 하는 경우다. 왜 굳이....? 혼자 생각한 결론은 '정규화'가 적절히되지 않은 PK가 FK의 성격을 가진 컬럼을 가진 테이블에서 원하는 데이터를 얻고 싶을 때 사용하는 것으로 보여진다. 예시를 들어 살펴보도록 하자.
https://leetcode.com/problems/employees-earning-more-than-their-managers/
해당 문제를 살펴보면, 부사수보다 사수가 봉급이 적은 경우를 select하라고 설명되어있다.
Id | Name | Salary | MangerId |
1 | Joe | 70000 | 3 |
2 | Henry | 80000 | 4 |
3 | Sam | 60000 | NULL |
4 | Max | 90000 | NULL |
ManagerId가 본인 사수의 Id값인데, Joe는 Sam , Henry는 Max가 사수로 볼 수 있다.
자기 자신에게 INNER JOIN 을 걸었음.
'IT > DB' 카테고리의 다른 글
SQL-UNION, UNION ALL (0) | 2021.09.01 |
---|---|
SQL 조건문 - CASE (0) | 2021.09.01 |
데이터 요약 GROUP BY & HAVING (0) | 2021.08.22 |
집계함수(COUNT/SUM/AVG/MIN/MAX) (0) | 2021.08.22 |
데이터 꺼내오기 (ORDER BY / SUBSTR,RIGTH,LEFT - 문자열자르기 / ROUND/CEIL/FLOOR - 소수점) (0) | 2021.08.16 |