Post

2.4 Having (SQL)

HAVING 개요

Table 0: Film Table

film_idtitlerental_ratelength
1명량4.99120
2암살2.9990
3어벤져스0.9980
4기생충2.9960
5어바웃 타임2.99100

HAVING은 집계 함수를 사용하여 데이터를 필터링하는 기능이다. Film 테이블에서 대여료(rental_rate)별로 집계했을 때 평균 상영 시간이 100분 미만인 대여료를 조회해보자. 일반적으로 조건 검색에는 WHERE 구문을 사용하지만, WHERE 구문에서는 집계 함수를 사용할 수 없다:

1
2
3
4
SELECT rental_rate FROM film WHERE AVG(length) < 100 GROUP BY rental_rate;

-- 조회 결과:
-- ERROR: Aggregate functions are not allowed in WHERE

위의 예시처럼 WHERE절 안에 집계 함수를 사용하게되면, 사용할 수 없다는 문구와 함께 오류를 반환한다. 이렇게 집계함수를 이용하여 조건을 걸고싶은 경우 WHERE 대신 HAVING을 사용하여 조회할 수 있다:

1
2
3
4
5
6
7
8
9
SELECT rental_rate FROM film GROUP BY rental_rate HAVING AVG(length) < 100;

-- 조회 결과:
-- +-----------+
-- |rental_rate|
-- +-----------+
-- |    0.99   |
-- |    2.99   |
-- +-----------+

WHERE와의 조합

WHERE와 HAVING을 조합하여 사용하면 복잡한 조건의 쿼리문을 작성할 수 있다. 예를 들어 대여료 (rental_rate)가 2.99가 아니고 대여료별로 집계했을 때 평균 상영시간이 100 미만인 대여료를 조회해보자:

1
2
3
4
5
6
7
8
SELECT rental_rate FROM film WHERE rental_rate != 2.99 GROUP BY rental_rate HAVING AVG(length) < 100;

-- 조회 결과:
-- +-----------+
-- |rental_rate|
-- +-----------+
-- |    0.99   |
-- +-----------+

GROUP BY를 기준으로 WHERE는 GROUP BY의 앞에, HAVING은 뒤에 위치한다. 이 쿼리는 다음과 같은 단계로 나누어 동작한다.

  1. FROM, WHERE, SELECT 절에 의한 데이터 조회
  2. GROUP BY로 지정된 컬럼으로 그룹화
  3. 집계 함수의 계산
  4. HAVING 절에 의한 필터링
  5. 결과의 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
                    +--------+---------+-----------+--------+
                    |film_id |  title  |rental_rate| length |
                    +--------+---------+-----------+--------+
                    |    1   |   명량   |   4.99    |   120  |
                    |    2   |   암살   |   2.99    |   90   |
                    |    3   |  어벤져스 |   0.99    |   80   |
                    |    4   |   기생충  |   2.99    |   60   |
                    |    5   |어바웃 타임 |   2.99    |  100   |
                    +--------+---------+-----------+--------+
                                       |
                                       |  (1)
                                       V
                    +--------+---------+-----------+--------+
                    |film_id |  title  |rental_rate| length |
                    +--------+---------+-----------+--------+
                    |    1   |   명량   |   4.99    |   120  |
                    |    3   |  어벤져스 |   0.99    |   80   |
                    +--------+---------+-----------+--------+
                                       |
                                       |  (2), (3)
                                       V
                           +-----------+--------+
                           |rental_rate|   avg  |
                           +-----------+--------+
                           |   0.99    |   80   |
                           |   4.99    |   120  |
                           +-----------+--------+
                                       |
                                       |  (4), (5)
                                       V
                           +-----------+--------+
                           |rental_rate|   avg  |
                           +-----------+--------+
                           |   0.99    |   80   |
                           +-----------+--------+
This post is licensed under CC BY 4.0 by the author.