> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL HAVING

> MySQL HAVING 절이 GROUP BY가 만든 그룹을 어떻게 걸러내는지, WHERE와 무엇이 다른지, 그리고 WHERE는 못 하는 열 별칭 참조를 왜 HAVING은 할 수 있는지 설명합니다.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

`WHERE`는 행이 그룹으로 묶이기 전에 행을 버립니다. `HAVING`은 그룹이 만들어진 뒤에 그룹 전체를 버립니다. 이 한 문장이 이 수업의 전부이고, 아래의 모든 내용은 그 결과입니다.

시작하기 전에 `mysql -u root -p sakila`로 클라이언트를 여세요.

## HAVING의 동작 방식

```sql theme={null}
SELECT GROUPING_COLUMN, AGGREGATE_FUNCTION(COLUMN_NAME)
FROM TABLE_NAME
GROUP BY GROUPING_COLUMN
HAVING GROUP_CONDITION;
```

`GROUPING_COLUMN`을 그룹을 정의하는 열로, `TABLE_NAME`을 테이블로, `AGGREGATE_FUNCTION(COLUMN_NAME)`을 그룹마다 계산할 것으로, `GROUP_CONDITION`을 `COUNT(*) > 200`처럼 그룹 전체에 적용되는 검사로 바꾸세요.

서버는 먼저 모든 그룹을 만든 다음, 조건이 참인 그룹만 남깁니다.

## 예제

### 큰 그룹만 남기기

```sql theme={null}
SELECT rating, COUNT(*) AS films
FROM film
GROUP BY rating
HAVING COUNT(*) > 200
ORDER BY rating;
```

```text theme={null}
+--------+-------+
| rating | films |
+--------+-------+
| PG-13  |   223 |
| NC-17  |   210 |
+--------+-------+
2 rows in set (0.01 sec)
```

5개의 등급이 모두 집계되었습니다. 그다음 그룹 3개가 검사에 통과하지 못해 버려졌습니다.

### HAVING은 별칭을 사용할 수 있습니다

별칭은 결과의 열에 이름을 붙이고, `HAVING`이 실행되는 시점에는 그 결과가 존재합니다.

```sql theme={null}
SELECT rating, COUNT(*) AS films
FROM film
GROUP BY rating
HAVING films > 200
ORDER BY rating;
```

```text theme={null}
+--------+-------+
| rating | films |
+--------+-------+
| PG-13  |   223 |
| NC-17  |   210 |
+--------+-------+
2 rows in set (0.00 sec)
```

같은 2개의 행이고, 더 짧게 씁니다. `WHERE`는 이렇게 할 수 없는데, 이름을 붙일 결과가 생기기 전에 실행되기 때문입니다: [WHERE](https://villagesql.com/docs/ko/tutorial/where.md) 수업이 대신 받게 되는 `ERROR 1054`를 보여줍니다.

### 한 쿼리에 두 절을 모두 쓰기

실제 쿼리는 대부분 둘 다 사용합니다: 행을 고르는 데 `WHERE`를, 그룹을 고르는 데 `HAVING`을 씁니다.

```sql theme={null}
SELECT rating, COUNT(*) AS films
FROM film
WHERE length > 120
GROUP BY rating
HAVING COUNT(*) > 100
ORDER BY rating;
```

```text theme={null}
+--------+-------+
| rating | films |
+--------+-------+
| PG-13  |   118 |
+--------+-------+
1 row in set (0.00 sec)
```

`WHERE`가 120분이 넘는 영화를 남겼고, 그룹화가 등급별로 그 수를 세었으며, `HAVING`이 그 수가 100을 넘는 등급 1개를 남겼습니다.

## 집계는 WHERE에 들어갈 수 없습니다

그 `HAVING` 조건을 `WHERE`로 옮기면 서버가 그대로 거부합니다.

```sql theme={null}
SELECT rating, COUNT(*) AS films
FROM film
WHERE COUNT(*) > 200
GROUP BY rating;
```

```text theme={null}
ERROR 1111 (HY000): Invalid use of group function
```

`WHERE`는 그룹화 전에 실행되므로, 검사할 개수가 없습니다. 집계의 별칭에도 같은 규칙이 적용되는데, 오류만 다릅니다.

```sql theme={null}
SELECT rating, COUNT(*) AS films
FROM film
WHERE films > 200
GROUP BY rating;
```

```text theme={null}
ERROR 1054 (42S22): Unknown column 'films' in 'where clause'
```

둘 다 같은 뜻이고 둘 다 같은 방법으로 고칩니다: 조건을 `HAVING`으로 옮기세요.

`WHERE`의 별칭에서 나는 `ERROR 1054`에는 2가지 해결 방법이 있고, 집계인지 아닌지가 둘을 가릅니다. 일반 표현식의 별칭은 `WHERE`에서 표현식을 되풀이해 쓸 수 있는데, [WHERE](https://villagesql.com/docs/ko/tutorial/where.md) 수업이 그것을 보여줍니다. 집계의 별칭은 위의 `ERROR 1111` 때문에 거기서 전혀 되풀이할 수 없으므로, `HAVING`으로 옮겨야 합니다.

## 어느 절이 무엇을 검사하는가

| 절 | 실행 시점 | 검사 대상 | 예 |
| - | - | - | - |
| `WHERE` | 그룹화 전 | 행 1개 | `WHERE length > 120` |
| `HAVING` | 그룹화 후 | 그룹 1개 전체 | `HAVING COUNT(*) > 50` |

행을 검사하는 조건은 언제나 `WHERE`에 두고, `HAVING`은 그룹이 존재해야만 뜻이 통하는 조건에만 쓰세요. 그쪽이 비용도 더 싼 배치인데, 그 이유는 [MySQL GROUP BY 성능](https://villagesql.com/docs/ko/guides/group-by-having.md) 가이드가 측정합니다.

> [!NOTE]
>
> `HAVING`에서 select 목록의 별칭을 참조하는 것은 MySQL 확장입니다. 같은 SQL이 다른 데이터베이스에서도 실행되어야 한다면 별칭 대신 집계를 되풀이해 쓰세요.

## 요약

* 그룹 전체를 버리려면 `HAVING`을, 행을 버리려면 `WHERE`를 사용하세요.
* `HAVING`은 `GROUP BY` 뒤에 실행되므로 집계를 검사할 수 있습니다.
* `ERROR 1111`은 `HAVING`에 있어야 할 집계가 `WHERE`에 있다는 뜻으로 읽으세요.
* `HAVING`에서는 열 별칭을 참조할 수 있고, `WHERE`는 그렇게 할 수 없습니다.
* 그룹이 아니라 행을 검사하는 조건은 `WHERE`에 두세요.

## 함께 보기

* [GROUP BY](https://villagesql.com/docs/ko/tutorial/group-by.md) — 이 절이 걸러내는 그룹 만들기
* [WHERE](https://villagesql.com/docs/ko/tutorial/where.md) — 먼저 실행되는 절
* [집계 함수](https://villagesql.com/docs/ko/tutorial/aggregate-functions.md) — 그룹 조건이 보통 검사하는 것
* [MySQL GROUP BY 성능](https://villagesql.com/docs/ko/guides/group-by-having.md) — 걸러내기 전에 그룹화하는 비용


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.