이번 장에서는 집계와 조건분기를 효율적으로 진행하는 방법을 알아보려고 한다.
1. 집계 대상으로 조건 분기
예제
문제
Population 테이블이 존재하며, 그 지역의 이름과 각 성별마다의 인구 정보를 담고 있다.

원하는 결과
지역의 성별에 따른 인구수를 한 row에 확인할 수 있도록 할 것.

1️⃣ union을 사용한 방법
각 성별마다의 인구수를 구해, union으로 합쳐 하나의 테이블로 정리하는 방법이다.
아래의 쿼리를 통해 3가지 속성을 가진 하나의 테이블로 정리가 가능하다.
select prefecture, pop as pop_men , null as pop_wom
from example.population
where sex = 1
union
select prefecture, null as pop_men,pop as pop_wom
from example.population
where sex = 2;

Group by 로 묶어 Sum 값을 구하게 되면, 각 지역마다 pop_men은 남자 인구수 + null 이기 때문에 온전한 남자 인구수를 가질 수 있다.
select prefecture, sum(pop_men) as pop_men , sum(pop_wom) as pop_wom
from(
select prefecture, pop as pop_men , null as pop_wom
from example.population
where sex = 1
union
select prefecture, null as pop_men,pop as pop_wom
from example.population
where sex = 2
) TMP
group by prefecture;

단점
where 절로 분기하여, union으로 머지하는 방법의 단점은 결국, 동일한 테이블을 두번 접근한다는 것이다.
2️⃣ CASE를 이용한 조건 분기
where 절에서 따로 조건 분기를 할 것이 아니라, select 구문에서 case로 조건분기하는 방법이다.
아래 쿼리는 sex(성별)이 1(남자)일때 pop의 온전한 값을 더하고, 아니면 0을 더하기 때문에 union을 이용했을 때와 똑같은 결과를 가질 수 있다.
select prefecture,
sum(case when sex = 1 then pop else 0 END) AS pop_men,
sum(case when sex = 2 then pop else 0 end) as pop_wom
from example.population
group by prefecture;
population 테이블에 한번만 접근할 수 있고, 쿼리가 간결해진다는 것이 장점이다.
2. 집약 결과로 조건 분기
예제
문제
Employees 테이블은 직원과 직원이 소속된 팀을 관리하는 테이블이다.

원하는 결과
조건에 맞춰 해당 직원의 팀 정보를 보여준다.
[조건]
- 소속된 팀이 1개라면 해당 팀 이름을 출력한다.
- 소속된 팀이 2개라면 ‘2개를 겸무’ 라는 문자를 출력한다.
- 소속된 팀이 3개 이상이라면 ‘3개 이상을 겸무’ 라는 문자를 출력한다.

1️⃣ union을 사용한 방법
소속된 팀이 1개인 사람들을 탐색하는 쿼리 + 소속된 팀이 2개인 사람들을 탐색하는 쿼리 + 소속된 팀이 3개인 사람들을 탐색하는 쿼리 ⇒ 이렇게 총 3개의 쿼리를 having으로 분기한 후 union으로 합친다.
- 소속된 팀이 1개인 사람들을 탐색하는 쿼리
select emp_name, max(team) as team
from example.employees
group by emp_name
having count(team) = 1 ;

- 소속된 팀이 2개인 사람들을 탐색하는 쿼리
select emp_name, '2개를 겸무' as team
from example.employees
group by emp_name
having count(team) = 2 ;

- 소속된 팀이 3개인 사람들을 탐색하는 쿼리
select emp_name, '3개를 이상을 겸무' as team
from example.employees
group by emp_name
having count(team) = 3 ;

- union으로 머지
select emp_name, max(team) as team from example.employees group by emp_name having count(team) = 1
union
select emp_name, '2개를 겸무' as team from example.employees group by emp_name having count(team) = 2
union
select emp_name, '3개를 이상을 겸무' as team from example.employees group by emp_name having count(team) = 3 ;

단점
이전과 동일하게, 동일한 테이블을 3번 접근한다는 것이 단점이며 쿼리가 너무 복잡하다.
2️⃣ CASE를 이용한 조건 분기
having 절에서 조건분기가 아닌 , select 구문에서 case로 조건분기하는 방법이다.
having을 이용하여 조건대로 나누지 않고, select 구문에서 조건에 맞게 원하는 값을 출력한다.
select emp_name,
case when count(*) = 1 then max(team)
when count(*) = 2 then '2개를 겸무'
when count(*) >= 3 then '3개 이상을 겸무'
end as team
from example.employees
group by emp_name;
이번에도 동일하게 테이블 접근 비용을 한번으로 줄일 수 있다. 또한 group by 의 hash 연산을 한번으로 줄일 수 있다.
.. 이전에 sql 테이블 접근과 리소스를 낭비하던 나는.. 정말 초보자가 맞는 것 같다..^^ 아잇 부끄러.. 앞으로 신경써야지 !!
'BOOK > SQL 레벨업' 카테고리의 다른 글
[SQL 레벨업] 15강 반복계의 공포 (1) | 2024.01.25 |
---|---|
[SQL 레벨업] 13강 자르기 (1) | 2024.01.23 |
[SQL 레벨업] 12강 집약 (0) | 2024.01.10 |
[SQL 레벨업] 10강 UNION이 필요한 경우 (1) | 2024.01.04 |
[SQL 레벨업] 8강 UNION을 사용한 쓸데없이 긴 표현 (0) | 2023.12.11 |