Backend/MySQL

SQL - Subquery

개발자의 첫 걸음 2025. 8. 10. 10:00

 

안녕하세요 오늘은 MySQL 사용하면서 복잡한 자료들을

 

필요한 것만 집어서 출력해 주는 도우미

 

서브쿼리에 대해 알아볼게요.

 

 

서브쿼리(Subquery)

 

서브쿼리는 메인 쿼리 내부에서 실행되는 하위쿼리(중첩쿼리)로

 

괄호 안에 작성하여 필요한 값을 먼저 추출한 뒤 메인 쿼리에 필요한 데이터를 동적으로 제공해 주는 역할을 해요.

 

간단하게 비유하자면 산수문제 중 괄호 안의 식을 먼저 풀어낸다고 생각해 주시면 됩니다.

 

 

서브쿼리의 특징

 

서브쿼리는 Select, From, Where 등 다양한 곳에 사용 가능하고,

 

하나의 값(단일 행) 또는 여러 값(다중 행)을 반환이 가능해요.

 

출력값을 한 번에 구할수 없고,  값을 두 번 나누어서 찾아야 할 경우 서브쿼리가 필요합니다.

 

 

서브쿼리 예시

 

# 	>> Bronze 등급이 아닌 회원의 이름과 등급 보기
# 1) 서브쿼리 없이 작성
SELECT name, grade
FROM `members`
WHERE
	grade != 'Bronze';
    
# 2) 서브쿼리 사용 작성
SELECT name, grade
FROM `members`
WHERE grade NOT IN (
	SELECT grade
    FROM `members`
    WHERE grade = 'Bronze'
);

SELECT name, grade FROM `members` 
WHERE grade NOT IN ('Silver', 'Gold', 'Platinum', 'Diamond');

-- (현재 예시) 서브쿼리 사용 VS 서브쿼리 미사용 --
# 서브쿼리 없이(!= 'Bronze')
# : 'Bronze'라는 값을 직접 비교
# - 정적인 조건 O (고정된 값)
# - 유연성 낮음
#		>> 'Bronze'외에 다른 등급이 생기거나 이름이 바뀌면 수정

# 서브쿼리 사용(동적으로 비교)
# : 서브쿼리로 먼저 'Bronze'를 찾아서, 해당 등급을 제외한 회원만 보여주는 방식
# - 서브쿼리를 통해 제외할 대상을 동적으로 구해오는 방식

# 차이점
# > 조건이 단순하고 고정: 빠르고 간단 (서브쿼리 X)
# > 조건이 복잡하거나 동적으로 바뀔 수 있음: 더 유연하고 안전 - NOT IN (서브쿼리)

 

 

 

서브쿼리가 필요한 예시

# 1) 구매한 이력이 있는 회원을 제외한 회원만 조회 (구매 이력이 없는 회원 조회)

SELECT name, member_id
FROM `members`
WHERE member_id NOT IN (
	-- 서브 쿼리 값이 동적으로 바뀔 수 있음
	SELECT DISTINCT member_id
	FROM `purchases`
);


# 2) 가장 포인트가 높은 회원 보기

SELECT name, points
FROM `members`
WHERE points = (
	-- 동적으로 가장 높은 포인트 점수를 계산해서 그 값과 일치한 레코드를 조회
    -- 항상 최신의 최대값을 반영 가능
    SELECT MAX(points)
    FROM `members`
);


# 3) 평균보다 높은 포인트를 가진 회원 조회
#  >> AVG()

SELECT AVG(points)
FROM `members`;

SELECT name, points
FROM `members`
WHERE points > (
	SELECT AVG(points)
    FROM `members`
);


# 4) 구매 금액이 가장 높은 회원 조회
# 	>> 그룹화 + 그룹 조건 + 정렬 + 제한

-- 구매 금액이 가장 높은 회원의 id 조회
SELECT member_id
FROM `purchases`
GROUP BY 
	member_id
ORDER BY
	SUM(amount) DESC
LIMIT 1;


# 위의 서브쿼리를 활용한 조회
SELECT member_id, name, points
FROM `members`
WHERE member_id = (
	SELECT member_id
	FROM `purchases`
	GROUP BY 
		member_id
	ORDER BY
		SUM(amount) DESC
	LIMIT 1
);


# >> purchases에서 회원별 구매 총액을 계산하고 가장 높은 사람 1명만 추출
#		: LIMIT, ORDER BY를 사용한 서브쿼리

추가적으로 어떠한 범위를 제외하거나(ex - 한 번도 구매하지 않은 회원 조회), 동적인 데이터계산에 권장해요.

 

특히 집계, 조건 비교, 연관 데이터 추출에 주로 사용하면 좋아요.

 

 

 

여기까지 MySQL의 서브쿼리를 알아봤는데요.

 

서브쿼리를 잘 활용한다면 복잡한 데이터들을 쉽게 정리할 수 있을 것 같아요.

 

 

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

SQL - Unique  (1) 2025.08.27
SQL - 구성 요소  (3) 2025.08.24
SQL - Select  (6) 2025.08.09
SQL 제약조건  (8) 2025.08.07
SQL의 무결성  (4) 2025.08.05