3. SQL의 조건 분기

ch 8. UNION을 사용한 쓸데없이 긴 표현

  • UNION을 사용한 조건 분기는 좋지 않다.
  • UNION은 내부적으로 여러개의 SELECT 구문을 실행하는 실행계획으로 해석된다 (= 테이블에 접근하는 횟수(I/O)가 늘어난다)

1) UNION을 사용한 조건 분기와 관련된 간단한 예제

  • UNION을 사용한 조건 분기
1
2
3
4
5
6
7
SELECT item_name, year, price_tax_ex AS price
		FROM Items
	WHERE year <= 2001
UNION ALL
SELECT item_name, year, price_tax_in AS price
		FROM Items
	WHERE year >= 2002
  • 단점 : 1. 길다, 2. 테이블에 2회 접근한다.

2) WHERE 구에서 조건 분기를 하는 사람을 초보자

1
2
3
4
SELECT item_name, year
	CASE WHEN year <= 2001 TEHN price_tax_ex
		WHEN year >= 2002 THEN price_tax_in END AS price
FROM Items

3) SELECT 구를 사용한 조건 분기의 실행 계획

  • 테이블 1회 접근으로 끝난다
  • 구문 => 식, UNION => CASE

ch 9. SELECT 구를 사용한 조건 분기의 실행 계획

1) 집계 대상으로 조건 분기

  • UNION을 사용한 방법
1
2
3
4
5
6
7
8
9
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 Population
	WHERE sex = '1' # 남성
	UNION
	SELECT prefecture, null AS pop_men, pop AS pop_wom
		FROM Population
	WHERE sex = '2') TMP # 여성
GROUP BY prefecture
  • 풀스캔이 2회 수행된다.

  • 집계의 조건 분기도 CASE 식을 사용

1
2
3
4
5
    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 Population
     GROUP BY prefecture;
  • 풀스캔이 1회로 감소한다.

2) 집약 결과로 조건 분기

  • 소속된 팀이 1개라면 해당 직원은 팀의 이름을 그대로 출력한다.
  • 2개라면 ‘2개를 겸무’로 출력
  • 3개라면 ‘3개를 겸무’로 출력
  • UNION을 사용한 조건 분기
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
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
  • 조건 분기가 레코드가 아닌 집합에 적용되기 때문에 WHERE가 아니라 HAVING에 쓰인다
  • 3번의 테이블 접근이 필요하다.
  • CASE 식을 사용한 조건 분기
1
2
3
4
5
6
7
SELECT emp_name,
		CASE WHEN COUNT(*) = 1 THEN MAX(team)
			 WHEN COUNT(*) = 2 THEN '2개를 겸무'
			 WHEN COUNT(*) >= 3 THEN '3개 이상을 겸무'
		EEND AS team
	FROM Employees
GROUP BY emp_name
  • 1번의 테이블 접근과 HASH 연산이 이뤄진다.

ch 10. 그래도 UNION이 필요한 경우

1) UNINON을 사용할 수 밖에 없는 경우

  • SELECT 하는 테이블이 다른 경우(FROM 구에서 테이블을 결합하고 CASE 식을 사용할 수 있으나 느려짐)

2) UNION을 사용하는 것이 성능적으로 더 좋은 경우

  • UNION을 사용할 때 인덱스 사용이 가능한 경우
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SELECT key, name,
		date_1, flg_1,
		date_2, flg_2,
		date_3, flg_3
	FROM ThreeElements
WHERE date_1='2013-11-01'
	AND flg_1='T'
UNION
SELECT key, name,
		date_1, flg_1,
		date_2, flg_2,
		date_3, flg_3
	FROM ThreeElements
WHERE date_2='2013-11-01'
	AND flg_2='T'
UNION
SELECT key, name,
		date_1, flg_1,
		date_2, flg_2,
		date_3, flg_3
	FROM ThreeElements
WHERE date_3='2013-11-01'
	AND flg_3='T'
  • OR을 사용하는 방법
1
2
3
4
5
6
7
8
SELECT key, name
		date_1, flg_1,
		date_2, flg_2,
		date_3, flg_3
	FROM ThreeElements
	WHERE (date_1 = '2013-11-01' AND flg_1 = 'T')
	OR (date_2 = '2013-11-01' AND flg_2 = 'T')
	OR (date_3 = '2013-11-01' AND flg_3 = 'T')
  • date와 flg에 인덱스가 된 경우 UNION이 더 빠를 수 있다

ch 11. 절차 지향형과 선언현

1) 구문 기반과 식 기반

  • 사고의 전환이 필요, 구문 -> 식