Database

서브쿼리(Subquery)의 모든 것: 복잡한 데이터도 쉽게 다루는 SQL 비법

코딩 코디네이터 2025. 4. 8. 18:37
반응형

서브쿼리(Subquery)의 모든 것
: 복잡한 데이터도 쉽게 다루는 SQL 비법

SQL 초보자라면 꼭 알아야 할 핵심 스킬! 서브쿼리만 잘 써도 데이터 조회, 갱신, 삭제가 훨씬 쉬워집니다!

 

 

안녕하세요, 데이터베이스를 처음 배우시는 분들께 정말 중요한 주제를 들고 왔습니다.

바로 서브쿼리(Subquery)입니다!

처음에는 좀 헷갈릴 수도 있지만, 개념만 제대로 잡고 나면 생각보다 쉽게 활용할 수 있답니다.

특히 오늘은 단순한 이론 설명에 그치지 않고, 실무에서 바로 써먹을 수 있는 실습 예제까지 준비했어요.

서브쿼리는 단일행/다중행 서브쿼리부터 시작해, 평균보다 비싼 상품 찾기, 데이터 갱신/삭제까지 아주 유용한 기능들을 갖추고 있습니다.

이번 글에서는 실제 SQL 쿼리와 결과를 함께 보면서 여러분이 서브쿼리를 완전히 이해할 수 있도록 도와드릴게요.

그럼 지금부터 하나씩 차근차근, 함께 살펴볼까요? 😊

1. 서브쿼리란? 기본 개념과 종류 정리

SQL을 공부하다 보면 이런 상황 한 번쯤은 겪게 됩니다.

“조건에 맞는 데이터를 조회하고 싶은데, 조건 자체가 또 다른 쿼리 결과여야 한다?”
이럴 때 서브쿼리(Subquery)가 등장하죠.

쉽게 말해,

쿼리 안에 또 다른 쿼리를 넣는 것입니다.

말 그대로 ‘하위 쿼리’라고도 불러요.

서브쿼리의 정의

서브쿼리는 SELECT, INSERT, UPDATE, DELETE 문의 내부에 포함되어 실행되는 SQL 쿼리입니다.

보통 괄호(()) 안에 위치하며, 외부 쿼리(Main Query)의 조건을 보조하는 역할을 해요.

서브쿼리의 위치별 분류

  • WHERE 절 서브쿼리: 특정 조건에 맞는 데이터를 필터링할 때 사용
  • FROM 절 서브쿼리: 서브쿼리를 테이블처럼 사용
  • SELECT 절 서브쿼리: 컬럼 값으로 서브쿼리 결과를 가져올 때 사용

서브쿼리의 종류: 단일행 vs 다중행

구분 설명 사용 예
단일행 서브쿼리 결과가 한 행만 반환됨 =, >, < 등의 연산자 사용
다중행 서브쿼리 결과가 여러 행을 반환함 IN, ANY, ALL 연산자 사용

✅ 실전에서 어떤 걸 써야 할까?

단일 결과가 필요한 조건(예: 평균, 최대값, 특정 ID)이라면 단일행 서브쿼리가 적합하고,

여러 조건 중 하나라도 일치하는 경우(예: 다수의 ID 목록, 특정 그룹)라면 다중행 서브쿼리가 필요합니다.

 

다음 단계에서는 이 두 가지 서브쿼리를 예제 중심으로 비교해보고, 실무에서 어떻게 활용되는지를 구체적으로 살펴볼게요. 🚀

 

 

2. 단일행 vs 다중행 서브쿼리 비교하기

서브쿼리를 사용하다 보면 가장 먼저 마주치는 갈림길이 바로 이것입니다.

"이 서브쿼리는 단일행일까, 다중행일까?" 이 둘은 쓰는 문법도 다르고, 오류 발생 가능성도 달라요.

그러니까 잘 구분해서 사용해야 합니다!

📌 단일행 서브쿼리

단일행 서브쿼리는 결과가 딱 하나만 나오는 경우입니다.

주로 집계 함수(AVG, MAX, MIN)를 쓴 서브쿼리에서 많이 볼 수 있어요.

 

💡 예제: 평균 급여보다 높은 급여를 받는 사원 찾기

SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

 

서브쿼리 (SELECT AVG(salary) ...)는 하나의 숫자(평균 급여)만 반환하죠?

그래서 외부 쿼리에서 salary > 평균 조건으로 비교할 수 있어요.

📌 다중행 서브쿼리

다중행 서브쿼리는 결과가 여러 행 나올 수 있는 경우예요.

이럴 땐 IN, ANY, ALL 같은 연산자를 사용해야 합니다.

 

💡 예제: 서울에 있는 고객에게만 상품을 판매한 직원 찾기

SELECT name
FROM employees
WHERE region_id IN (SELECT region_id FROM regions WHERE city = 'Seoul');

 

SELECT region_id ... 서브쿼리는 여러 개의 지역 ID를 반환할 수 있어요.

그럼 외부 쿼리는 IN (여러 값) 형태로 처리해야죠.

🎯 단일/다중행 서브쿼리, 이렇게 구분하세요!

항목 단일행 서브쿼리 다중행 서브쿼리
결과 수 1행 (1개 값) 여러 행
대표 연산자 =, >, <, >= 등 IN, ANY, ALL
예외 발생 다중 결과시 오류 발생 단일 연산자 사용시 오류

 

정리하자면,

결과 행의 수를 기준으로 서브쿼리를 판단하고, 그에 맞는 연산자를 선택해야 합니다.

 

다음 장에서는 이 개념을 바탕으로 실제로 서브쿼리를 활용해서 복잡한 데이터 조회를 어떻게 수행하는지 보여드릴게요!

 

 

3. 복잡한 데이터 조회에 서브쿼리 활용하기

서브쿼리를 진짜 멋지게 활용할 수 있는 타이밍이 바로 복잡한 조건의 데이터 조회입니다.

단일 테이블에서 끝나는 단순한 SELECT 쿼리는 물론, 두 개 이상의 테이블을 연결하거나 특정 조건을 가진 집계 데이터를 찾을 때도 서브쿼리는 빛을 발하죠.

🎯 활용 예 1: 평균보다 높은 급여를 받는 부서의 사원 목록

SELECT name, department_id, salary
FROM employees
WHERE salary > (
  SELECT AVG(salary)
  FROM employees
);

 

이 쿼리는 모든 직원의 평균 급여를 먼저 계산한 후, 그보다 높은 급여를 받는 직원만 조회합니다.

복잡해 보이지만, 서브쿼리 하나로 매우 직관적인 쿼리를 완성할 수 있어요!

🎯 활용 예 2: 최근 주문한 고객 정보 조회

SELECT customer_id, name
FROM customers
WHERE customer_id IN (
  SELECT customer_id
  FROM orders
  WHERE order_date >= CURDATE() - INTERVAL 30 DAY
);

 

orders 테이블에서 최근 30일 내 주문한 고객 ID만 추출한 후, 그 ID들을 바탕으로 customers 테이블에서 상세 정보를 가져오는 방식입니다.

이중 조회가 필요한 케이스에서 아주 강력한 무기예요.

🎯 활용 예 3: 가장 많이 주문한 상품 조회

SELECT product_name
FROM products
WHERE product_id = (
  SELECT product_id
  FROM order_items
  GROUP BY product_id
  ORDER BY COUNT(*) DESC
  LIMIT 1
);

 

이 쿼리는 서브쿼리 안에서 ORDER BY + LIMIT를 사용해 가장 많이 팔린 상품 하나를 찾고, 그 상품의 이름을 외부 쿼리로 가져오는 방식입니다.

💡 FROM 절에 쓰는 인라인 서브쿼리도 있다?

서브쿼리는 WHERE절에만 사용하는 게 아니에요.

FROM 절에 서브쿼리를 넣으면, 그것 자체가 하나의 가상 테이블처럼 작동합니다.

SELECT dept_summary.department_id, dept_summary.total_salary
FROM (
  SELECT department_id, SUM(salary) AS total_salary
  FROM employees
  GROUP BY department_id
) AS dept_summary
WHERE total_salary > 1000000;

 

이런 방식은 복잡한 그룹 연산을 미리 처리하고, 그 결과를 다시 필터링하거나 정렬할 때 정말 유용해요.

📌 Tip: JOIN보다 서브쿼리가 유리한 상황

  • 집계 결과로 필터링해야 할 때 (ex. 평균, 최대값 기반 조건)
  • 조건에 맞는 특정 값만 필요할 때 (ex. 최신 데이터 1건만)
  • 중첩 필터링이 필요한 복잡한 조건문 구성 시

이제 서브쿼리를 어떻게 응용하면 복잡한 조건에서도 깔끔하게 원하는 데이터를 뽑을 수 있는지 감이 좀 오셨죠?

다음은 바로 실습 시간입니다! 😊

AVG를 활용해 평균보다 비싼 상품만 골라보는 예제로 넘어가 보죠!

 

 

4. 실습예제 ① : 평균보다 비싼 상품 조회

실습 예제를 통해 서브쿼리를 직접 써보면 확실히 개념이 잘 잡히죠!

이번 예제에서는 상품 테이블(products)에서 전체 평균 가격보다 비싼 상품들만 골라보겠습니다.

🎯 목표

  • 전체 상품의 평균 가격을 계산한다.
  • 평균보다 높은 가격의 상품들만 조회한다.

📋 사용 테이블 구조 (products)

컬럼명 데이터 타입 설명
product_id INT 상품 고유 ID
product_name VARCHAR 상품명
price DECIMAL 상품 가격

💻 실습 SQL

SELECT product_name, price
FROM products
WHERE price > (
  SELECT AVG(price) FROM products
);

 

이 쿼리는 단일행 서브쿼리를 사용한 대표적인 예입니다.

내부 쿼리 SELECT AVG(price)는 하나의 평균값을 반환하고, 외부 쿼리는 그 값을 기준으로 조건을 걸어줍니다.

💬 실습 팁

  • 서브쿼리가 먼저 실행되고, 그 결과를 외부 쿼리가 이용해 조건 비교합니다.
  • 테이블에 따라 AVG 결과가 소수점이 나오기 때문에 ROUND() 함수를 함께 사용해도 좋습니다.

이제 서브쿼리를 직접 써봤으니 감이 조금 오시죠? 😎

 

다음은 서브쿼리로 데이터를 갱신하거나 삭제하는 예제로 이어가 볼게요.

 

 

5. 실습예제 ② : 서브쿼리로 데이터 갱신/삭제하기

서브쿼리는 단순히 데이터를 조회하는 데만 쓰이는 게 아닙니다!

UPDATEDELETE에도 아주 효과적으로 활용할 수 있어요.

이번엔 데이터를 바꾸거나 지울 때 서브쿼리를 어떻게 활용하는지 실습 예제를 통해 익혀볼게요.

🎯 예제 1: 가장 적게 팔린 상품의 가격 10% 인하

UPDATE products
SET price = price * 0.9
WHERE product_id = (
  SELECT product_id
  FROM order_items
  GROUP BY product_id
  ORDER BY COUNT(*) ASC
  LIMIT 1
);

 

위 쿼리는 order_items 테이블에서 가장 적게 팔린 상품을 찾아내고, 해당 상품의 가격을 10% 인하하는 업데이트 작업을 수행합니다.

서브쿼리를 통해 조건 대상을 정하고, 외부 쿼리에서 그 값을 기반으로 갱신하는 방식이죠.

🎯 예제 2: 주문한 적 없는 고객 삭제

DELETE FROM customers
WHERE customer_id NOT IN (
  SELECT DISTINCT customer_id
  FROM orders
);

 

이번엔 삭제입니다!

orders 테이블에 등장하지 않은 고객 ID만 찾아내서, customers 테이블에서 해당 고객들을 제거합니다.

NOT IN과 서브쿼리 조합은 이런 "조건부 삭제"에 자주 사용됩니다.

💬 실무 꿀팁

  • UPDATE/DELETE에 서브쿼리를 쓸 때는 SELECT 먼저 테스트 해보는 게 안전합니다.
  • 서브쿼리가 다중 결과를 반환할 가능성이 있다면 IN, EXISTS를 고려해 보세요.
  • DELETE 전에 항상 백업을! 데이터는 소중하니까요 😥

서브쿼리를 단순 조회뿐 아니라 갱신과 삭제에도 유용하게 활용할 수 있다는 것, 이제 확실히 느끼셨을 거예요.

 

 

6. 마무리 

지금까지 서브쿼리의 개념부터 다양한 활용 예제까지 쭉 따라오신 여러분, 정말 고생 많으셨어요!

처음엔 다소 낯설고 복잡하게 느껴질 수 있지만, 막상 실무에 들어가 보면 서브쿼리를 얼마나 자주 쓰는지 놀라실 거예요.

이제는 단순한 SELECT 문을 넘어서 데이터를 요리하듯 다룰 수 있는 능력이 생긴 겁니다!

📌 실무 활용 꿀팁 요약

  • 서브쿼리 결과는 꼭 행 수를 예측하고 연산자를 선택해야 합니다 (= vs IN).
  • SELECT문 외에도 UPDATE, DELETE에도 서브쿼리를 적극 활용해보세요.
  • FROM 절에서 사용하는 인라인 뷰도 실무에서 많이 등장합니다.
  • 서브쿼리로 처리 가능한 로직은 JOIN보다 더 깔끔하고 효율적일 수 있음!

끝으로 하나만 더 강조드릴게요.

서브쿼리는 조건을 동적으로 만들 수 있는 강력한 도구입니다.

SQL 초보 단계에서 서브쿼리를 자유자재로 다룰 수 있게 되면, 그 자체로 실력자라고 불릴 만한 자격이 충분해요! 🔥

오늘 배운 예제들, 꼭 실습하면서 손에 익혀보시길 추천드릴게요.

 

반응형