SQL 왕초보 가이드

[SQL 02] GROUP BY & 집계 함수 완벽 가이드 | 데이터 분석을 위한 필수 SQL 📊

devnewsletter 2025. 2. 6. 09:17
반응형

GROUP BY, HAVING, COUNT, SUM, AVG... 익숙하지만 제대로 알고 계신가요? 실무 데이터 분석에 꼭 필요한 집계 함수 활용법을 예제와 함께 쉽게 배워보세요! 📊


SQL 왕초보 가이드 - 2단계: 다중 테이블 조인과 실전 연습! 🎯

📢 SQL이 점점 재밌어지죠?

여러분, JOIN을 배워보니 SQL이 조금 익숙해졌나요? 😊
하지만 현실 데이터는 두 테이블에만 있는 게 아니죠!
이번에는 3개 이상의 테이블을 조인하는 방법자기 자신을 조인하는 SELF JOIN, 그리고 집계 함수(GROUP BY) 등을 실습해볼 거예요! 🚀


1️⃣ 다중 테이블 조인 (INNER JOIN 여러 번 사용)

👉 직원(employees), 부서(departments), 프로젝트(projects)를 조인해볼까요?

목표:

  • 직원(employee_name), 부서(department_name), 프로젝트(project_name) 정보를 가져오기

📌 예제 테이블 스키마

CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(50),
    department_id INT
);

CREATE TABLE departments (
    department_id INT PRIMARY KEY,
    department_name VARCHAR(50)
);

CREATE TABLE projects (
    project_id INT PRIMARY KEY,
    project_name VARCHAR(50),
    employee_id INT
);

 

📌 예제 데이터

INSERT INTO employees VALUES (1, 'Alice', 1), (2, 'Bob', 2), (3, 'Charlie', 3);
INSERT INTO departments VALUES (1, 'HR'), (2, 'IT'), (3, 'Sales');
INSERT INTO projects VALUES (1, 'Project A', 1), (2, 'Project B', 2);

 

📌 기대 결과

employee_name department_name project_name
Alice HR Project A
Bob IT Project B

 

📌 SQL 정답

SELECT employee_name, department_name, project_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
JOIN projects p ON e.employee_id = p.employee_id;

설명:

  • JOIN2번 사용하여 3개의 테이블을 연결했어요!
  • INNER JOIN이므로 프로젝트가 없는 직원은 결과에서 제외됩니다.

📌 프로젝트가 없는 직원도 포함하려면?

SELECT employee_name, department_name, project_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
LEFT JOIN projects p ON e.employee_id = p.employee_id;

 

📌 기대 결과 (모든 직원 포함)

employee_name department_name project_name
Alice HR Project A
Bob IT Project B
Charlie Sales NULL

2️⃣ SELF JOIN 활용 - 직원 & 상사 정보 조회

👉 SELF JOIN을 활용해 직원과 상사를 조회해볼까요?

목표:

  • 각 직원(employee_name)과 해당 직원의 상사(manager_name) 조회

📌 예제 테이블 스키마

CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(50),
    department_id INT,
    manager_id INT
);

 

📌 예제 데이터

INSERT INTO employees VALUES (1, 'Alice', 1, NULL), (2, 'Bob', 2, 1), (3, 'Charlie', 3, 1);

 

📌 기대 결과

employee_name manager_name
Bob Alice
Charlie Alice

 

📌 SQL 정답

SELECT e1.employee_name, e2.employee_name AS manager_name
FROM employees e1
JOIN employees e2
ON e1.manager_id = e2.employee_id;

설명:

  • employees 테이블을 자기 자신과 JOIN하여 직원과 상사를 연결했어요.

📌 모든 직원(상사가 없는 직원 포함)을 출력하려면?

SELECT e1.employee_name, e2.employee_name AS manager_name
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.employee_id;

 

📌 기대 결과 (모든 직원 포함)

employee_name manager_name
Alice NULL
Bob Alice
Charlie Alice

3️⃣ GROUP BY 활용 - 각 부서별 직원 수 조회

👉 부서별로 직원이 몇 명인지 세볼까요?

📌 기대 결과

department_name employee_count
HR 1
IT 1
Sales 1

 

📌 SQL 정답

SELECT d.department_name, COUNT(*) AS employee_count
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;

설명:

  • GROUP BY를 사용하면 같은 부서에 속한 직원들을 하나로 묶고, 개수를 셀 수 있어요!

📌 직원이 없는 부서도 포함하려면?

SELECT d.department_name, COUNT(e.employee_id) AS employee_count
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_name;

 

📌 기대 결과 (직원이 없는 부서 포함)

department_name employee_count
HR 1
IT 1
Sales 1
Marketing 0

 

💡 COUNT(*) vs COUNT(컬럼명)의 차이

COUNT() 함수 NULL 값 포함 여부 설명
COUNT(*) ✅ 포함 테이블의 모든 행을 계산 (NULL 값도 포함됨)
COUNT(컬럼명) ❌ 제외 해당 컬럼이 NULL이 아닌 행만 계산

4️⃣ HAVING 활용 - 직원이 2명 이상인 부서만 조회

👉 직원이 2명 이상인 부서만 조회해볼까요?

📌 예제 데이터

INSERT INTO employees VALUES (4, 'David', 1);

 

📌 기대 결과

department_name employee_count
HR 2

 

📌 SQL 정답

SELECT d.department_name, COUNT(*) AS employee_count
FROM departments d
JOIN employees e ON e.department_id = d.department_id
GROUP BY d.department_name
HAVING COUNT(*) >= 2;

설명:

  • HAVING COUNT(*) >= 2를 사용하여 직원이 2명 이상인 부서만 필터링합니다.

📌 직원이 없는 부서까지 포함하고 직원이 2명 이상인 부서만 필터링하려면?

예제 상황이 다소 엉뚱할 수 있지만, SQL 동작 방식을 쉽게 이해하기 위한 설정이니 참고해주세요! 😆🚀

SELECT d.department_name, COUNT(e.employee_id) AS employee_count
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_name
HAVING COUNT(e.employee_id) >= 2;

 

💡두 쿼리의 차이점 정리

차이점 첫 번째 쿼리 (JOIN + COUNT(*)) 두 번째 쿼리 (LEFT JOIN + COUNT(e.employee_id))
직원이 없는 부서 포함 여부 아예 제외됨 포함됨 (NULL로 표시됨)
COUNT() 방식 COUNT(*) (NULL 포함) COUNT(e.employee_id) (NULL 제외)
최종 결과에서 직원 없는 부서 (Marketing) 애초에 JOIN에서 제외됨 0이지만 HAVING에서 제거됨
성능 ✅ 빠름 ❌ 느림 (불필요한 NULL 값 처리 필요)

🎯 2단계 마무리!

오늘 배운 개념들 정리해볼까요? 🚀

다중 테이블 조인 (INNER JOIN 여러 번 사용)
SELF JOIN을 활용한 직원 & 상사 관계 조회
GROUP BY를 활용한 부서별 직원 수 집계
HAVING을 활용한 조건 필터링

📌 다음 단계에서는 SQL 최적화 및 성능 향상 기법을 다룰 예정이에요!
SQL을 더 빠르고 효율적으로 사용하는 법, 궁금하지 않나요? 😆

 


관련 시리즈 몰아보기

[SQL 01] JOIN 쉽게 이해하기 | 초보자를 위한 SQL 기초 강좌 📊

[SQL 03-1] 서브쿼리 최적화 | 성능을 10배 높이는 실전 가이드 🚀

 

반응형