반응형

GROUP BY와 집계함수로 배우는 데이터 분석의 첫걸음

카테고리별 상품 수?
월별 가입자 수?
이제는 직접 SQL로 뽑아보세요!

 

 

안녕하세요, 여러분 😊

오늘은 데이터 그룹화(GROUP BY)집계함수(aggregation functions)에 대해 알아보려 합니다.

SQL에서 GROUP BY는 데이터를 요약하거나 집계할 때 아주 자주 등장하는 기능인데요,

COUNT, SUM, AVG 같은 집계함수와 함께 사용하면 통계 리포트를 만드는 건 물론, 비즈니스 인사이트까지 얻을 수 있답니다.

이번 글에서는 이 개념들을 이론적으로 정리하고, 실제로 어떤 식으로 실무에서 활용되는지 실습 예제를 통해 확인해 볼 거예요.

예를 들어

"카테고리별 상품 수", "월별 회원 가입자 수", "상품별 평균 가격" 같은 데이터, 궁금하지 않으세요?

오늘 딱 정리해드릴게요!

1. GROUP BY란 무엇인가요? 🤔

여러분, SQL로 데이터를 다루다 보면

"이 항목별로 몇 개나 있지?",

"카테고리별 평균은 얼마지?" 같은 질문, 자주 하게 되죠?

바로 그럴 때 사용하는 게 GROUP BY 구문이에요.

🔍 GROUP BY의 역할

GROUP BY는 지정한 컬럼의 값을 기준으로 레코드를 그룹화합니다.

그리고 각 그룹별로 집계함수(COUNT, SUM 등)를 적용할 수 있게 해주는 강력한 기능이죠.

📌 기본 문법 구조

SELECT 컬럼명, 집계함수()
FROM 테이블명
GROUP BY 컬럼명;

📋 예제: 상품 테이블을 기준으로

SELECT category, COUNT(*) AS 상품수
FROM products
GROUP BY category;

 

위 쿼리는 products 테이블에서 category별로 몇 개의 상품이 있는지를 알려줘요.

'식품', '가전', '의류' 등으로 묶어서 몇 개씩 있는지 보는 거죠!

📊 GROUP BY를 쓸 때 주의할 점

  • SELECT절에는 GROUP BY 컬럼 또는 집계함수만 포함할 수 있어요.
  • GROUP BY에 쓰인 컬럼은 결과에도 반드시 포함되어야 해요.
  • WHERE절은 그룹화 전에 필터링, HAVING절은 그룹화 후 필터링에 사용돼요.

🧠 한 줄 요약

GROUP BY는 데이터를 묶어서 요약하고 싶을 때 쓰는 SQL의 핵심 기능!

COUNT, SUM 같은 집계함수와 찰떡궁합이에요 💡

 

 

2. 집계함수의 기본 개념과 종류 🧮

GROUP BY와 함께 가장 많이 쓰이는 것이 바로 집계함수(aggregate functions)입니다.

이 함수들은 데이터를 요약해서 보여줄 때 아주 유용한데요,

쉽게 말해

"합계", "평균", "개수", "최대값", "최소값" 같은 걸 계산할 때 쓰는 함수들이에요.

📌 자주 사용하는 집계 함수 5가지

함수 설명 예시
COUNT() 데이터 개수를 셉니다. COUNT(*)
SUM() 값들의 총합을 계산합니다. SUM(price)
AVG() 평균값을 계산합니다. AVG(score)
MIN() 가장 작은 값을 찾습니다. MIN(age)
MAX() 가장 큰 값을 찾습니다. MAX(salary)

✅ 실제 사용 예시

SELECT category, COUNT(*) AS 상품수, SUM(price) AS 총매출
FROM products
GROUP BY category;

 

위 쿼리는 카테고리별 상품 수와 총 매출을 동시에 보여주는 대표적인 예시예요.

GROUP BY 없이 COUNT나 SUM만 쓰면 전체 합계만 구해지니까, 꼭 함께 써야 의미 있는 데이터가 나와요!

💡 TIP

  • COUNT는 NULL 값을 무시하지만 COUNT(*)는 NULL도 포함해요!
  • AVG는 숫자 컬럼에만 사용할 수 있어요. 문자열은 안 됩니다!

정리하자면,

집계함수는 단순히 값을 보는 데서 끝나는 게 아니라 분석의 방향성을 잡는 데 꼭 필요한 도구들이에요.

실무에서는 거의 필수! 👍

 

 

3. GROUP BY와 집계함수 함께 쓰기 🔗

지금까지 GROUP BY집계함수의 개념을 따로따로 살펴봤다면,

이제 이 둘을 실제로 조합해보는 실전 단계로 넘어가볼까요?

이 조합은 마치 커피와 설탕처럼, 함께 쓸 때 훨씬 맛있는(!) 결과를 내줘요 😄

💻 기본 사용 예제

SELECT region, COUNT(*) AS 고객수, AVG(age) AS 평균나이
FROM customers
GROUP BY region;

 

위 쿼리는 고객들을 region(지역)별로 묶은 후, 각 지역의 고객 수평균 나이를 보여줍니다.

요약하자면, GROUP BY는 묶고 집계함수는 계산한다는 거죠.

📌 WHERE절 vs HAVING절

구문 적용 시점 예시
WHERE GROUP BY 전에 레코드 필터링 WHERE age > 20
HAVING GROUP BY 후 그룹 필터링 HAVING COUNT(*) > 10

즉, WHERE은 그룹화 전에 개별 데이터를 거르고, HAVING은 그룹화된 결과에서 조건을 적용해요.

두 절을 동시에 사용할 수도 있다는 것도 기억해 두세요!

🔥 실무 감각 익히기: 다중 집계 함수

SELECT department, COUNT(*) AS 직원수, SUM(salary) AS 총급여, MAX(salary) AS 최고연봉
FROM employees
GROUP BY department;

 

이렇게 여러 집계 함수를 동시에 써서 부서별 통계 리포트를 뽑을 수 있어요.

분석 보고서 만들 때 자주 쓰이는 유형이니 익혀두면 정말 유용하답니다.

📣 한 문장 요약!

GROUP BY + 집계함수 = 실무 보고서의 기본 구조!

쿼리를 구성할 때 WHERE, HAVING, SELECT의 순서를 꼭 신경 써주세요 🛠️

 

 

4. 실전 예제 ① : 카테고리별 상품 수와 매출 구하기 🛍️

이제 이론은 충분히 봤으니, 진짜 데이터를 기준으로 실습을 해봐야겠죠?

가장 자주 사용되는 예제 중 하나인 카테고리별 상품 수와 총 매출 구하기를 같이 해봅시다!

🗂️ 가정 테이블: products

컬럼명 설명
product_id 상품 고유 ID
product_name 상품명
category 상품 카테고리
price 상품 가격

💡 목표

  • 각 카테고리마다 상품이 몇 개 있는지 세기
  • 각 카테고리별 상품의 가격 합계를 구하기

🧑‍💻 SQL 예제

SELECT category, COUNT(*) AS 상품수, SUM(price) AS 총매출
FROM products
GROUP BY category;

 

이 쿼리는 카테고리 기준으로 데이터를 그룹화하고, 각 그룹별로 상품 개수와 총 가격을 계산합니다.

정말 실무에서 많이 쓰이는 유형이에요!

📊 결과 예시

category 상품수 총매출
전자기기 5 1,200,000
의류 8 950,000
식품 12 480,000

✅ 정리

카테고리별로 데이터를 그룹화한 뒤, COUNT()SUM()을 조합하면 상품 수와 매출을 한눈에 볼 수 있어요.

이건 마케팅, 판매, 재고 분석 등 여러 부서에서 애용하는 대표 쿼리랍니다!

 

 

 

5. 실전 예제 ② : 월별 회원 가입자 수 구하기 📆

이번에는 시간 기준으로 데이터를 그룹화하는 방법을 소개할게요.

예를 들어,

"2024년 3월에 가입한 회원 수는 몇 명일까?" 같은 질문에 답하려면 날짜 데이터를 월 단위로 그룹화해야 해요.

이건 정말 다양한 실무 분석 리포트에서 핵심적인 쿼리랍니다!

📁 가정 테이블: members

컬럼명 설명
member_id 회원 고유 번호
join_date 가입일 (DATE 형식)
email 이메일 주소

🧑‍💻 SQL 예제: 월별 그룹화

SELECT DATE_FORMAT(join_date, '%Y-%m') AS 가입월, COUNT(*) AS 가입자수
FROM members
GROUP BY 가입월
ORDER BY 가입월;

 

여기서 핵심은 DATE_FORMAT(join_date, '%Y-%m') 구문입니다.

가입일에서 연도-월(YYYY-MM)만 추출해서 그룹화하는 거죠.

📊 결과 예시

가입월 가입자수
2024-01 143
2024-02 167
2024-03 194

📌 정리

시간 데이터를 분석할 때는 반드시 그룹핑 포맷을 지정해줘야 해요.

'월', '분기', '연도' 단위로 자유롭게 요약이 가능하고, 마케팅 타이밍 분석, 사용자 행동 패턴 파악 등에 아주 유용하죠!

정말 이건 써보면 무조건 배우게 되는 기능이에요 😎

 

 

6. 마무리 🧾

오늘은 SQL에서 GROUP BY집계함수를 활용하는 핵심 개념과 실전 예제를 함께 살펴봤어요.

단순한 데이터 나열을 넘어, 카테고리별 분석, 월별 추이 분석까지 할 수 있다는 건 정말 매력적인 부분이죠.

 

특히나 COUNT(), SUM(), AVG() 같은 함수들은 실무 리포트 작성 시 거의 필수라고 해도 과언이 아니에요.

여기에 DATE_FORMAT과 같은 날짜 가공까지 잘 활용하면, 원하는 데이터를 뽑아내는 능력은 몇 단계 업그레이드됩니다 🚀

처음에는 살짝 복잡하고 헷갈릴 수 있지만, 실습을 반복하다 보면 자연스럽게 손에 익을 거예요.

 

다음 시간에는 HAVING절 활용법, 서브쿼리 등을 추가로 소개하며 좀 더 복합적인 분석을 해볼게요.

직접 SQL로 실습해보는 거, 꼭 추천드립니다.

"눈으로 보지 말고 손으로 실행하라!" 이 말, 데이터 공부에선 진짜 진리예요 😄

반응형
반응형

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

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

 

반응형
반응형

다양한 JOIN 활용하기: 테이블 관계를 한눈에!

"이런 데이터를 어떻게 뽑지?"
JOIN을 이해하면, 테이블 간 데이터 연결이 보입니다.
실무에서 가장 많이 쓰이는 SQL JOIN의 모든 것을 쉽게 알려드릴게요!

 

 

안녕하세요, 여러분 😊

개발자든 데이터 분석가든, SQL을 다루다 보면 언젠가는 반드시 마주치는 벽이 있죠. 바로 JOIN입니다!

JOIN은 데이터베이스에서 테이블 간 관계를 연결하고 원하는 데이터를 통합할 수 있게 해주는 정말 강력한 기능인데요.

하지만 처음 배우는 분들에게는 그 개념이 꽤나 헷갈릴 수 있어요.

그래서 오늘은 JOIN의 개념부터 실무 예제까지, 실전 중심으로 하나하나 친절하게 설명해드리려고 해요.

특히 회원, 주문, 상품 테이블을 JOIN해서 판매 리포트까지 만드는 실습을 함께 해볼 거예요!

1. INNER JOIN, LEFT JOIN, RIGHT JOIN 개념 정리 ✨

SQL에서 JOIN은 두 개 이상의 테이블을 연결해 하나의 결과로 만들어주는 기능이에요.

이 JOIN은 데이터베이스 관계형 모델의 핵심 개념 중 하나로, 테이블 간의 관계(Relation)를 활용해 데이터를 종합하는 데 사용되죠.

JOIN의 종류는 다양하지만, 그중에서도 가장 자주 사용하는 세 가지가 바로

INNER JOIN, LEFT JOIN, RIGHT JOIN입니다.

1-1. INNER JOIN 🧩

INNER JOIN은 두 테이블에서 공통된 값이 존재하는 행만 결과로 가져와요.

즉, 교집합을 구한다고 생각하면 편해요.

SELECT *
FROM orders
INNER JOIN members ON orders.member_id = members.id;

→ 주문한 회원만 조회하고 싶을 때 자주 사용합니다.

1-2. LEFT JOIN 🧭

LEFT JOIN은 왼쪽 테이블은 모두 가져오고, 오른쪽 테이블에 매칭되는 값이 있으면 같이 보여줘요.

즉, 왼쪽 기준 전체 데이터 + 오른쪽 매칭되는 데이터!

SELECT *
FROM members
LEFT JOIN orders ON members.id = orders.member_id;

→ 주문하지 않은 회원까지 모두 조회해야 할 때 유용합니다.

1-3. RIGHT JOIN ➡️

RIGHT JOIN은 LEFT JOIN의 반대 개념이에요.

오른쪽 테이블은 모두 보여주고, 왼쪽 테이블과 매칭되는 데이터를 함께 보여줍니다.

SELECT *
FROM orders
RIGHT JOIN members ON orders.member_id = members.id;

→ 오른쪽 테이블 중심으로 보고 싶을 때 쓰지만, 대부분 LEFT JOIN으로 처리하는 경우가 많아요.

1-4. JOIN 비교 요약표 📊

JOIN 종류 결과 설명 대표 사용 예
INNER JOIN 양쪽 모두에 일치하는 데이터만 실제로 주문한 회원만 조회
LEFT JOIN 왼쪽 테이블 전체 + 오른쪽 매칭 모든 회원 + 주문 여부 확인
RIGHT JOIN 오른쪽 테이블 전체 + 왼쪽 매칭 모든 주문 기록 + 회원 여부 확인

 

이제 JOIN의 기본 개념이 조금은 명확해지셨죠? 😊

다음 파트에서는 "왜 실무에서 이렇게까지 JOIN을 많이 쓰는지" 그 이유를 살펴볼 거예요.

실제 현업에서는 데이터 연결 없이는 아무것도 할 수 없거든요.

그럼 계속해서 다음 목차로 넘어가 볼게요!

 

 

2. 실무에서 JOIN을 활용하는 이유 💡

JOIN이 실무에서 왜 이렇게 중요할까요?

간단히 말해,

현실 세계의 데이터는 대부분 하나의 테이블에 담기지 않기 때문이에요.

회원 정보는 `members` 테이블, 주문 정보는 `orders`, 상품 정보는 `products`에 따로 저장돼 있죠.

그럼 결국, 우리가 원하는 "의미 있는 데이터 분석"을 하려면 이 테이블들을 묶어주는 JOIN이 필수라는 뜻이에요.

2-1. 실제 서비스는 '관계형' 데이터 구조로 설계된다

예를 들어볼게요. 여러분이 쿠팡 같은 쇼핑몰을 만든다고 가정해 봅시다.

  • 회원은 여러 번 주문할 수 있고,
  • 하나의 주문에는 여러 상품이 들어갈 수 있으며,
  • 상품은 다른 주문에도 포함될 수 있어요.

→ 이처럼 실제 서비스는 '하나의 테이블'로 해결되지 않으며, 테이블 간의 관계를 표현하고 연결해주는 JOIN이 꼭 필요해요.

2-2. JOIN이 필요한 실전 사례들 🔍

상황 JOIN 이유
회원별 총 주문 금액 조회 회원 + 주문 테이블을 JOIN해서 합계 계산
상품별 판매 실적 분석 주문 상세 + 상품 테이블을 JOIN
로그인한 사용자 주문 내역 조회 세션 기반 사용자 ID로 JOIN하여 조회

2-3. JOIN을 모르면 겪게 되는 문제들 ⚠️

  • 단일 테이블에 모든 데이터를 저장하려고 함 → DB 설계 실패
  • 필요한 데이터를 뽑지 못해 리포트, 분석 등 무력해짐
  • 성능 저하를 유발하는 서브쿼리 반복

JOIN을 자유자재로 활용하는 사람과 그렇지 않은 사람의 실력 차이는, 데이터를 문장으로 이해하느냐, 실제로 활용할 수 있느냐의 차이라고 생각해요.

 

그럼 다음은 본격적인 실습을 위한 준비! 회원-주문-상품 테이블의 구조를 먼저 이해해보도록 할게요.

구조를 모르고 JOIN하면 의미가 없으니까요 😉

 

 

3. 회원-주문-상품 테이블 구조 이해 🧱

자, 이제 JOIN 실습을 하기 전에 먼저 어떤 테이블이 존재하고, 이들 사이에 어떤 관계가 있는지부터 명확하게 이해해야 해요.

우리가 사용할 데이터베이스에는 총 3개의 테이블이 있습니다:

  1. 회원 테이블 (members)
  2. 주문 테이블 (orders)
  3. 상품 테이블 (products)

이 세 테이블은 각각 독립적으로 존재하지만, 외래 키(Foreign Key)를 통해 서로 연결됩니다.

3-1. 테이블 구조 및 관계도 📘

테이블 주요 컬럼 설명
members id, name, email 회원 정보 저장
orders id, member_id, product_id, quantity 주문 정보 저장, 회원/상품과 연결됨
products id, name, price 상품 정보 저장

 

이 구조에서 핵심은 orders 테이블이 중간 다리 역할을 한다는 거예요.

이 테이블 덕분에 "어떤 회원이 어떤 상품을 주문했는가?"를 알 수 있죠.

3-2. 관계형 데이터 ERD 도식화 🔗

간단한 관계도를 텍스트로 나타내면 다음과 같아요:

members (1) ──── (N) orders (N) ──── (1) products

→ 회원 1명이 여러 주문 가능,

→ 하나의 주문은 하나의 상품을 가리킴,

→ 같은 상품이 여러 주문에 포함될 수 있음!

3-3. 실습을 위한 샘플 데이터 📦

실습을 위해 아래와 같은 샘플 데이터를 구성해둘게요.

테이블 샘플 데이터 예시
members (1, '홍길동', 'hong@example.com')
orders (1001, 1, 2001, 2)
products (2001, 'USB 메모리', 12000)

→ 이제 이 데이터를 JOIN해서 "누가 어떤 상품을 몇 개 샀는지"를 알 수 있겠죠?

 

자, 테이블 구조도 이해했고 준비는 끝났습니다.

다음 파트에서는 본격적으로 JOIN을 활용한 실습을 시작해볼게요!

궁금했던 JOIN의 실제 동작 방식, 이제 직접 눈으로 확인할 시간입니다 🔥

 

 

4. JOIN으로 테이블 관계 조회하기 🔍

자, 이제 본격적인 실습 시간이에요!

앞서 소개한 회원(members), 주문(orders), 상품(products) 테이블을 JOIN해서 데이터를 조회해볼게요. 이 실습을 통해 실제 서비스에서 JOIN이 어떻게 활용되는지 체감할 수 있어요.

4-1. 회원 + 주문 정보 조회 (INNER JOIN)

SELECT m.id AS member_id, m.name, o.id AS order_id, o.quantity
FROM members m
INNER JOIN orders o ON m.id = o.member_id;

→ 주문을 한 회원만 조회됩니다. (주문하지 않은 회원은 결과에 포함되지 않음)

4-2. 주문 + 상품 정보 조회 (INNER JOIN)

SELECT o.id AS order_id, p.name AS product_name, p.price, o.quantity
FROM orders o
INNER JOIN products p ON o.product_id = p.id;

→ 주문 내역에 포함된 상품의 이름과 가격까지 확인 가능해요.

4-3. 회원 + 주문 + 상품 전체 JOIN (3개 테이블 연결)

SELECT m.name AS member_name, p.name AS product_name, p.price, o.quantity
FROM members m
INNER JOIN orders o ON m.id = o.member_id
INNER JOIN products p ON o.product_id = p.id;

회원이 어떤 상품을 얼마나 주문했는지를 정확히 알 수 있어요.

4-4. LEFT JOIN으로 주문 없는 회원까지 조회

SELECT m.name AS member_name, o.id AS order_id
FROM members m
LEFT JOIN orders o ON m.id = o.member_id;

모든 회원을 보여주되, 주문이 있는 경우만 주문 번호가 함께 나옵니다. (주문이 없는 회원은 NULL로 표시됨)

4-5. 실습 결과 예시 🎯

회원명 상품명 가격 수량
홍길동 USB 메모리 12000 2

여기까지 진행하셨다면, 이제 JOIN의 기본적인 사용법은 거의 마스터하신 거예요! 👏

이제 다음 파트에서는 JOIN을 활용한 리포트 생성이라는 한 단계 높은 실습으로 넘어가볼게요.

단순 조회를 넘어서, 집계, 분석, 정렬까지 같이 경험해봐야 진짜 실무 활용이 되니까요!

 

 

5. 실습: 다양한 JOIN으로 리포트 만들기 📊

지금부터 JOIN을 활용해서 판매 실적 리포트를 만들어보겠습니다.

단순 조회를 넘어서서, 집계(SUM), 그룹핑(GROUP BY), 정렬(ORDER BY)까지 함께 써볼 거예요.

이게 바로 진짜 실무에서 매일 하는 SQL이에요.

5-1. 상품별 총 판매 수량 리포트

SELECT p.name AS product_name, SUM(o.quantity) AS total_sold
FROM orders o
INNER JOIN products p ON o.product_id = p.id
GROUP BY p.name
ORDER BY total_sold DESC;

→ 어떤 상품이 얼마나 많이 팔렸는지 순서대로 확인할 수 있어요.

5-2. 회원별 총 구매 금액 리포트

SELECT m.name AS member_name, SUM(p.price * o.quantity) AS total_spent
FROM members m
INNER JOIN orders o ON m.id = o.member_id
INNER JOIN products p ON o.product_id = p.id
GROUP BY m.name
ORDER BY total_spent DESC;

→ 어떤 회원이 가장 많이 결제했는지 알 수 있어요.

     마케팅 타깃 추출이나 VIP 등급 관리에 바로 써먹을 수 있어요!

5-3. 월별 판매 실적 리포트

이번엔 날짜가 저장되어 있다고 가정하고, 주문일 기준으로 월별 실적도 만들어볼게요.

아래는 주문 테이블에 order_date 컬럼이 있는 경우입니다.

SELECT DATE_FORMAT(o.order_date, '%Y-%m') AS month, SUM(p.price * o.quantity) AS monthly_revenue
FROM orders o
INNER JOIN products p ON o.product_id = p.id
GROUP BY month
ORDER BY month ASC;

→ 월별 매출 분석! 보고서, 대시보드, 매출 트렌드 예측 등에 사용됩니다.

5-4. 리포트 실전 응용 팁 💡

  • 집계 함수 + GROUP BY 조합은 실무에서 필수!
  • 리포트용 쿼리는 항상 ORDER BY로 정렬까지!
  • 복잡해지면 서브쿼리 또는 CTE로 나누기

여기까지 잘 따라오셨다면,

이제 단순 SELECT 쿼리를 넘어서 데이터 분석 실무에서 필요한 JOIN 활용 능력을 갖추셨다고 볼 수 있어요!

이제 마지막으로 JOIN 마스터를 위한 실전 꿀팁만 정리하고 마무리할게요 😉

 

 

6. JOIN 마스터를 위한 실전 팁 🔧

JOIN을 이론으로만 배웠다면 아직 반쪽짜리예요.

실제 프로젝트, 운영 서버, 대용량 데이터에서 JOIN은 성능, 구조, 가독성 등 다양한 고민이 함께 따라옵니다.

이 파트에서는 JOIN을 잘 쓰는 사람들의 실무 노하우를 공유할게요!

6-1. JOIN 성능 최적화 핵심 포인트

  • ON 절의 컬럼은 반드시 인덱스가 있는지 확인할 것!
  • 필요한 컬럼만 SELECT 해서 속도와 메모리 낭비 줄이기
  • WHERE 조건은 JOIN보다 아래쪽에 두는 게 가독성에 좋음

6-2. 실무에서 자주 쓰는 JOIN 패턴

JOIN은 다음과 같은 실무 시나리오에서 자주 사용됩니다:

JOIN 활용 시나리오 예시
회원별 주문 내역 조회 members + orders
상품별 누적 판매 집계 orders + products + GROUP BY
접속 로그 기반 행동 분석 users + logs + actions

6-3. JOIN 쿼리 디버깅 꿀팁

  • JOIN 결과가 비정상일 때는 테이블 별 단독 SELECT로 먼저 확인하기
  • WHERE 조건이 NULL과 연관된 경우에는 IS NULL 주의
  • 쿼리 복잡할수록 CTE(Common Table Expression) 활용 추천

🚀 마무리하며

JOIN은 단순히 문법만 익히는 것이 아니라, "데이터 구조를 연결해서 의미를 찾아내는 능력"입니다.

기본 개념 → 실습 → 리포트 → 최적화까지 익히셨다면, 이제 JOIN은 여러분의 강력한 무기가 될 거예요.

 

다음에 더 복잡한 관계형 쿼리나 성능 튜닝, 실시간 분석 쿼리까지도 도전해보세요!

JOIN은 처음이 어렵지, 익숙해지면 누구보다 유용한 툴이 될 거예요 😉

반응형

+ Recent posts