본문 바로가기
SQL

[SQL] 조건 분기 CASE,UNION 차이

by UnoCode 2020. 8. 31.

이전 글에서 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

댓글