MySQL

Group By 와 having 절

ryeonng 2024. 6. 10. 16:34

Group By 절

SQL에서 특정 열의 값에 따라 행 집합을 요약된 그룹으로 나누는 데 사용된다.

이 절은 주로 집계 함수 ( 예 : SUM, AVG, MAX, MIN, COUNT 등 ) 와 함께 사용되어, 각 그룹에 대한 요약 정보를 제공한다.

  • GROUP BY 절은 데이터들을 원하는 그룹으로 나눌 수 있다.
  • 나누고자 하는 그룹의 컬럼명을 SELECT 절과 GROUP BY 절 뒤에 추가하면 된다.
  • 집계 함수와 함께 사용되는 GROUP BY 절에 추가하지 않아도 된다.

 

HAVING 절

HAVING 절은 GROUP BY 절과 함께 사용되며, 특정 조건을 만족하는 그룹만을 필터링하는 데 사용된다.

WHERE 절이 개별 행에 대해 조건을 적용하는 반면, HAVING 절은 그룹화된 결과에 대한 조건을 적용한다.

집계 함수의 결과를 기반으로 조건을 적용할 수 있기 때문에 GROUP BY 절 이후 사용된다.

 

예제

고등학교에서 다양한 클래스의 학생들이 시험을 치렀다고 가정 해 보자.

각 클래스 별 평균 점수가 70점 이상인 클래스만을 찾고 싶을 때 사용할 수 있는 SQL 쿼리를 작성하였다.

id
name
class
score
1
Alice
A
85
2
Bob
B
75
3
Charlie
A
65
4
David
A
70
5
Eve
B
95
6
Frank
C
88
7
Grace
C
92
8
Hannah
B
78
9
Ian
A
85
10
Jill
C
90

 

create database mydb3;

CREATE TABLE tb_student (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    class CHAR(1) NOT NULL,
    score INT NOT NULL
);
    
  
INSERT INTO tb_student (name, class, score) VALUES
('Alice', 'A', 85),
('Bob', 'B', 75),
('Charlie', 'A', 65),
('David', 'A', 70),
('Eve', 'B', 95),
('Frank', 'C', 88),
('Grace', 'C', 92),
('Hannah', 'B', 78),
('Ian', 'A', 85),
('Jill', 'C', 90);

-- 전체 조회
select * from tb_student;

-- 1단계 : 클래스 별로 그룹화 시켜 보자.
select class, avg(score) as avreagescore
from tb_student
group by class; -- 클래스 별로 그룹화 한다.

-- 2단계 : 위와 같이 클래스 별로 그룹화 된 결과 집합에서 필터링을 적용하기 (ex)80점 이상만 보고싶음)
select class, avg(score) as 평균
from tb_student
group by class
having 평균 >= 80; -- ★★★ having 절의 조건은, 결과 집합이 먼저 생성된 후를 기준으로 필터 조건을 설정해야 한다 ! 

-- 문제 : 각 클래스에서 가장 높은 점수와 가장 낮은 점수를 찾아 보세요.
select class, max(score) as 최고점수, min(score) as 최저점수
from tb_student
group by class
having 최고점수 >= 93;

-- 참고 ! 
-- 만약 낮은 버전의 db를 사용한다면, 별칭의 컬럼이 적용되지 않을 수 있다.

 

CREATE TABLE tb_employees ( 
    employee_id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    department VARCHAR(50) NOT NULL,
    salary INT NOT NULL
);

INSERT INTO tb_employees (name, department, salary) VALUES
('John Doe', 'Sales', 48000000),
('Jane Smith', 'Sales', 55000000),
('Alice Johnson', 'Marketing', 50000000),
('Chris Lee', 'Marketing', 45000000),
('Bob Brown', 'HR', 35000000),
('Patricia Pink', 'HR', 40000000),
('Michael White', 'Engineering', 75000000),
('Anna Black', 'Engineering', 65000000),
('Linda Green', 'Engineering', 72000000),
('James Red', 'Engineering', 68000000),
('Larry Blue', 'Sales', 52000000),
('Jessica Purple', 'Sales', 51000000),
('Amber Yelow', 'Marketing', 47000000),
('Peter Orange', 'HR', 43000000),
('Lisa Teal', 'HR', 39000000);

select * from tb_employees;

-- 문제1 : 각 부서 별 평균 급여 계산 (단, 소수점은 제거)
select department, round(avg(salary), 0) as 평균급여
from tb_employees
group by department;

-- 문제2 : 평균 급여가 50000000 이상인 부서를 찾으세요.
select department, round(avg(salary), 0) as 평균급여
from tb_employees
group by department
having 평균급여 >= 50000000;

-- 문제3 : 각 부서에서 가장 높은 급여를 받는 직원의 금액을 출력하세요.
select department, max(salary) as 최고급여
from tb_employees
group by department;

-- 문제4 : 특정 부서에서 근무하는 직원 수가 3명 이상인 부서만 출력하세요.
select department, count(department) as 직원수
from tb_employees
group by department
having 직원수 >= 3;

-- 문제5 : 각 부서 별 평균 급여와 직원 수를 출력하세요.
select department, round(avg(salary)) as 평균급여, count(department) as 직원수
from tb_employees
group by department;

-- order by(asc, desc) 와 limit , 그리고 offset
-- order by 의 기본 값은 오름차순 / 내림차순은 desc
select id, name, class, score
from tb_student
where score > 80
order by score desc
limit 3; -- 반환 할 결과의 개수 제한

-- offset 이해 : (3, 0) 두 번째 숫자가 limit가 되고, 앞의 숫자가 offset이 된다.
-- offset : 시작의 위치. ★ 0 번 부터 시작된다. ★ 3번이면 4번째 숫자부터 출력된다.
select id, name, class, score
from tb_student
limit 3, 3

 

 

'MySQL' 카테고리의 다른 글

MySQL 계정 생성 및 권한  (0) 2024.06.10
SQL 쿼리의 일반적인 처리 순서  (0) 2024.06.10
MySQL Function  (0) 2024.06.07
테이블 복사 및 데이터 추가  (0) 2024.06.07
MySQL JOIN  (1) 2024.06.07