이전 글에서 CASE문에 대해 간략히 배웠습니다.
보통 조건을 분기를 할 때 CASE문을 사용합니다. 하지만 CASE문 이외에도 조건 분기에 사용할 수 있는 구문이 있습니다.
그것은 바로 UNION입니다.
하지만 UNION을 조건 분기에 사용한다면 안좋은 예시라고 볼 수 있습니다. UNION은 사용하기 쉽다는 장점이 있지만 SQL에 있어서 조건 분기를 위해 존자하는 구문이 아니기 때문입니다.
따라서 이번시간에는 UNION이 왜 초보자 기술인지 왜 사용하면 안좋은지에 대해 다루어 보겠습니다.
WHERE 구문 조금씩 다른 여러개의 SELECT 구문을 합쳐서, 복수의 조건에 일치하는 하나의 결과 집합을 얻고 싶을 때 사용합니다.
이른 방법은 성능적인 측명에서 굉장히 큰 단점을 가지고 있고 하나의 SQL구문이 실행되는것 처럼 보이지만 여러 개의 SELECT 구문을 실행 계획으로 해석되어 DB hit되는 횟수가 많다고 볼 수 있습니다.
간단한 예제를 보겠습니다.
item_id | year | item_name | price_tax_ex | price_tax_in |
100 | 2000 | Spoon | 500 | 525 |
100 | 2001 | Spoon | 520 | 546 |
100 | 2002 | Spoon | 600 | 630 |
100 | 2003 | Spoon | 600 | 630 |
101 | 2000 | Chopsticks | 500 | 525 |
101 | 2001 | Chopsticks | 500 | 525 |
101 | 2002 | Chopsticks | 500 | 525 |
101 | 2003 | Chopsticks | 500 | 525 |
UNINO을 사용한 조건 분기
SELECT item_name, year, price_tax_ex as price
FROM product
WHERE year <= 2000
UNION ALL
SELECT item_name, year, price_tax_in as price
FROM product
WHERE year >= 2002
실행 계획
EXPLAIN
SELECT item_name, year, price_tax_ex as price
FROM product
WHERE year <= 2000
UNION ALL
SELECT item_name, year, price_tax_in as price
FROM product
WHERE year >= 2002
안타깝습니다. 테이블 스켄이 2번 사용하는군요..
데이터 양이 컷을때를 생각해 보면 데이터 캐시도 기대하기 어려우니 더욱 성능이 저하되겠네요..
CASE문을 이용한 조건 분기
SELECT item_name, year,
CASE WHEN year <= 2001 THEN price_tax_ex
WHEN year >= 2002 THEN price_tax_in END AS price
FROM product
실행 계획
같은 결과를 내어 주지만 쿼리가 1번만 hit되는것을 알 수 있습니다.
성능적으로는 2배의 차이가 난다고 볼 수 있죠..
집계와 조건 분기
이번에는 집계에서 UNION을 사용할 경우 쓸데없이 문장이 길어지죠 ㅋㅋ
pop 테이블
지역 | 성별 | 인구 |
성남 | 남 | 60 |
성남 | 여 | 40 |
수원 | 남 | 90 |
수원 | 여 | 100 |
광명 | 남 | 100 |
광명 | 여 | 50 |
일산 | 남 | 100 |
일산 | 여 | 100 |
용인 | 남 | 20 |
용인 | 여 | 200 |
UNION
SELECT prefecture, SUM(pop_man) AS pop_man, SUM(pop_won) AS pop_won
FROM (SELECT prefecture,pop AS pop_man, null AS pop_won
FROM pop
WHERE sex = "남"
UNION
SELECT prefecture,null AS pop_won, pop AS pop_man
FROM pop
WHERE sex = "여") POP
GROUP BY prefecture
실행 계획
ALL : 풀스켄이 2번 실행되는 군요.. 안타깝습니다.
CASE
CASE 식의 응용 방법으로 유명한 표측/표두 레이아웃 이동 문제입니다.
SELECT prefecture,
SUM(CASE WHEN sex="남" THEN pop ELSE 0 END) AS pop_man,
SUM(CASE WHEN sex="여" THEN pop ELSE 0 END) AS pop_won
FROM pop
GROUP BY prefecture
실행 계획
좀더 복잡한 예제를 보도록 할까요?
UNION
Employees 테이블
emp_id | team_id | emp_name | team |
201 | 1 | Joe | 상품기획 |
201 | 2 | Joe | 개발 |
201 | 3 | Joe | 영업 |
202 | 2 | Jim | 개발 |
203 | 3 | Carl | 영업 |
204 | 1 | Bree | 상품기획 |
204 | 2 | Bree | 개발 |
204 | 3 | Bree | 영업 |
204 | 4 | Bree | 관리 |
205 | 1 | Kim | 상품기획 |
205 | 2 | Kim | 개발 |
다음과 같은 결과를 얻을 것입니다.
- 소속된 팀이 1개라면 해당 직원은 팀 이름을 그대로 출력
- 소속된 팀이 2개라면 해당 직원은 '2개를 겸무'라는 문자열을 출력
- 소속된 팀이 3개 이상이라면 해당 직원은 '3개 이상 겸무'라는 문자열 출력
SELECT emp_name,
MAX(team) AS team
FROM employees
GROUP BY emp_name
HAVING COUNT(*) = 1
UNION
SELECT emp_name,
'2개 겸무' AS team
FROM employees
GROUP BY emp_name
HAVING COUNT(*) = 2
UNION
SELECT emp_name,
'3개 이상 겸무' AS team
FROM employees
GROUP BY emp_name
HAVING COUNT(*) >= 3
실행 계획
CASE구문
SELECT emp_name,
CASE WHEN COUNT(*) = 1 THEN MAX(team)
WHEN COUNT(*) = 2 THEN '2개 겸무'
WHEN COUNT(*) >= 3 THEN '3개 이상 겸무'
END AS team
FROM employees
GROUP BY emp_name
실행 계획
CASE 식을 사용해서 DB hit를 3분의 1로 줄일 수 있습니다.
GROUP BY의 HASG연산도 3회에서 1회로 줄었습니다.
'SQL' 카테고리의 다른 글
[SQL] 집약 (0) | 2020.09.02 |
---|---|
[SQL] 어쩔 수 없는 UNION (1) | 2020.09.01 |
[SQL] SQL 조건 분기, 집합 연산, 윈도우 함수, 갱신 (0) | 2020.08.30 |
[SQL] DBMS 아키텍처 Part 2 (0) | 2020.08.29 |
[SQL] DBMS 아키텍처 Part 1 (0) | 2020.08.28 |
댓글