데이터로그😎

[MySQL] JOIN 🆚 서브쿼리 본문

SQL/MySQL

[MySQL] JOIN 🆚 서브쿼리

지연v'_'v 2024. 1. 4. 17:49

*모든 글의 내용은 아래의 사이트를 참고하여 작성했습니다.

 

[MYSQL] 📚 JOIN과 서브쿼리 차이 및 변환 💯 정리

조인(JOIN) vs 서브쿼리(Sub Query) 조인과 서브쿼리는 때로 동일한 결과를 얻을 수 있다. 상황에 따라 조인을 사용하는 것이 훨씬 좋을 때도 있고, 반면에 서브 쿼리를 사용하는 것이 좋을 때도 있다.

inpa.tistory.com

 


서브쿼리(Subquery) vs 조인(JOIN)

1. 서브쿼리

  • 하나의 쿼리 안에 다른 쿼리가 포함된 것을 말한다.
  • 메인 쿼리라 불리는 외부 쿼리가 있고, 외부 쿼리 내에 다른 내부 쿼리문이 있다.

2. 조인(JOIN)

  • 여러개의 쿼리가 필요하지 않다.
  • 2개 이상의 테이블을 특정 기준에 따라 연결하고, 연결한 최종 테이블로부터 열을 조회하도록 하는 기능이다. 
🚨서브쿼리는 가독성이 좋다. 그러나 JOIN에 비해 성능이 좋진 않다. 

 

 


예시

product와 sale테이블이 있다. 아래의 3가지 질문에 답해보며 서브쿼리와 조인을 비교해볼 것이다.

 

[product 테이블]

id name cost year city
1 chair 245.00 2017 Chicago
2 armchair 500.00 2018 Chicago
3 desk 900.00 2019 Los Angeles
4 lamp 85.00 2017 Cleveland
5 bench 2000.00 2018 Seattle
6 stool 2500.00 2020 Austin
7 tv table 2000.00 2020 Austin

 

[sale 테이블]

id product_id (외래키) price year city
1 2 2000.00 2020 Chicago
2 2 590.00 2020 New York
3 2 790.00 2020 Cleveland
5 3 800.00 2019 Cleveland
6 4 100.00 2020 Detroit
7 5 2300.00 2019 Seattle
8 7 2000.00 2020 New York

 

 

# 문제1) 2,000달러에 팔린 product의 이름과 가격을 알아보자

① JOIN

SELECT P.name, P.cost
FROM sale S
JOIN product P
ON S.product_id = P.id
WHERE S.price = 2000 ;

 

② 서브쿼리

SELECT name, cost
FROM product
WHERE id IN (SELECT product_id
			FROM sale
            WHERE price = 2000);

**서브쿼리를 WHERE문 안에 놓을 때는 product 테이블의 모든 id와 서브쿼리문의  product_id를 비교할 때마다 서브쿼리문이 실행된다. 이 때,  비교할 때마다 내부 쿼리를 계속 반복해서 실행하기 때문에 속도, 성능이 낮아진다.

 

결과

name cost
armchair 500.00
tv table 2000.00

 

 

# 문제2)  판매된 상품의 이름과 가격을 알아보자

① JOIN

SELECT DISTINCT P.name, P.cost
FROM product P
JOIN SALE S
ON P.id = S.product_id;

 

② 서브쿼리

SELECT name, cost
FROM product
WHERE id IN (SELECT DISTINCT product_id
			FROM sale);

 

결과

name cost
armchair 500.00
desk 900.00
lamp 85.00
bench 2000.00
tv table 2000.00

 

# 문제 3) 판매되지 않은 상품들의 이름과 가격을 알아보자

① JOIN

SELECT DISTINCT P.name, P.cost
FROM product P
LEFT JOIN sale S
ON P.id = S.product_id
WHERE S.product_id IS NULL;

 

LEFT JOIN을 사용하게 되면 product 테이블의 모든 행은 보여지고, product 테이블에 있는 id와 동일한 product_id를 가진 sale 테이블의 row는 정상적으로 보여지게 된다. 그러나 product 테이블에는 있지만 sale 테이블에는 없는 상품은 NULL로 보여지게 된다. 아래와 같이 말이다.
sale테이블에는 2,3,4,5,7 상품만 존재하고 1,6은 존재하지 않는다. 따라서 id가 1, 6인 상품은 sale 테이블에는 존재하지 않기 때문에 sale테이블의 id, product_id, price, year, city 정보는 최종 테이블에서 null로 보여지는 것이다.

| id | name      | cost   | year | city       | id  | product_id | price   | year | city       |
|----|-----------|--------|------|------------|-----|------------|---------|------|------------|
| 1  | chair     | 245.00 | 2017 | Chicago    | null| null       | null    | null | null       |
| 2  | armchair  | 500.00 | 2018 | Chicago    | 1   | 2          | 2000.00 | 2020 | Chicago    |
| 2  | armchair  | 500.00 | 2018 | Chicago    | 2   | 2          | 590.00  | 2020 | New York   |
| 2  | armchair  | 500.00 | 2018 | Chicago    | 3   | 2          | 790.00  | 2020 | Cleveland  |
| 3  | desk      | 900.00 | 2019 | Los Angeles| 5   | 3          | 800.00  | 2019 | Cleveland  |
| 4  | lamp      | 85.00  | 2017 | Cleveland  | 6   | 4          | 100.00  | 2020 | Detroit    |
| 5  | bench     | 2000.00| 2018 | Seattle    | 7   | 5          | 2300.00 | 2019 | Seattle    |
| 6  | stool     | 2500.00| 2020 | Austin     | null| null       | null    | null | null       |
| 7  | tv table  | 2000.00| 2020 | Austin     | 8   | 7          | 2000.00 | 2020 | New York   |

 

LEFT JOIN을 실행한 후 WHERE문에서 sale 테이블의 product_id가 NULL인 상품들만 골라서 보려한다. 즉, 판매되지 않은 상품들을 의미한다. 이들은 id가 1, 6인 상품일테니 최종 테이블은 아래와 같다.

 

결과

name cost
chair 245.00
stool 2500.00

 

② 서브쿼리

SELECT name, cost
FROM product
WHERE id NOT IN (SELECT DISTINCT product_id
					FROM sale)

 


 

그러나, JOIN과 SUBQUERY가 서로 대체될 수 없는 경우도 있다.이 때는 SUBQUERY문에 집계가 실행될 때이다. 

 

*서브쿼리 내에서 집계된 단일 값을 WHERE 절에서 외부 쿼리의 값과 비교할 때

SELECT name
FROM product
WHERE cost < (SELECT AVG(price) FROM sale);

 

SELECT city, sum_price
FROM 
(
	SELECT city, SUM(price) as sum_price
    FROM sale
    GROUP BY city
	) s
WHERE sum_price < 2100;

'SQL > MySQL' 카테고리의 다른 글

[MySQL] 데이터 모델링  (0) 2024.01.10
[MySQL] 데이터베이스 & 유저 생성  (0) 2024.01.01
[MySQL] 테이블 생성, 입력, 수정, 삭제  (0) 2023.12.29
[MySQL] 테이블 정보 확인  (0) 2023.12.29
[MySQL] 날짜형식 관련 함수  (0) 2023.12.29