> ## 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 서브쿼리

> MySQL 서브쿼리로 한 쿼리가 다른 쿼리의 답을 쓰는 방식, 서브쿼리가 나타날 수 있는 위치, 그리고 서브쿼리가 너무 많은 행을 반환할 때 ERROR 1242가 뜻하는 것입니다.

> [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 →

서브쿼리는 다른 쿼리 안에 있는 쿼리입니다. 아직 모르는 답을 쓸 수 있게 해 줍니다: 가장 긴 영화, 평균 평점, 무언가와 일치하는 id의 집합 같은 것입니다. 서브쿼리가 없다면 2개의 쿼리를 실행하고 첫 번째 결과를 두 번째에 손으로 붙여 넣어야 합니다.

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

## 서브쿼리의 동작 방식

```sql theme={null}
SELECT COLUMN_LIST
FROM TABLE_NAME
WHERE COLUMN_NAME = (SELECT AGGREGATE_FUNCTION(COLUMN_NAME) FROM TABLE_NAME);
```

`COLUMN_LIST`를 원하는 열로, `TABLE_NAME`을 테이블로, `COLUMN_NAME`을 검사할 열로, `AGGREGATE_FUNCTION`을 비교 대상 값을 만드는 함수로 바꾸세요.

서버는 서브쿼리를 실행하고, 그 결과를 가져와, 바깥 쿼리에서 사용합니다.

정확히 1개의 행과 1개의 열을 반환하는 괄호 안의 서브쿼리는 스칼라 서브쿼리이고, 값처럼 동작합니다. 아래의 형태가 그것이고, 가장 자주 잘못되는 형태이기도 합니다.

## 예제

### 적어 둘 수 없는 값 사용하기

가장 긴 영화의 길이를 모르므로, 그 자리에서 요청합니다.

```sql theme={null}
SELECT title, length
FROM film
WHERE length = (SELECT MAX(length) FROM film)
ORDER BY title;
```

```text theme={null}
+--------------------+--------+
| title              | length |
+--------------------+--------+
| CHICAGO NORTH      |    185 |
| CONTROL ANTHEM     |    185 |
| DARN FORRESTER     |    185 |
...
+--------------------+--------+
10 rows in set (0.00 sec)
```

`MAX(length)`만으로는 185 외에는 아무것도 주지 않습니다. 서브쿼리가 그것을 `WHERE`에 다시 넣어 주므로 영화도 함께 얻습니다.

### SELECT 목록의 서브쿼리

같은 값을 SELECT 목록에 넣을 수도 있고, 거기서는 모든 행에 반복됩니다.

```sql theme={null}
SELECT title, length, (SELECT AVG(length) FROM film) AS catalog_mean
FROM film
ORDER BY title
LIMIT 3;
```

```text theme={null}
+------------------+--------+--------------+
| title            | length | catalog_mean |
+------------------+--------+--------------+
| ACADEMY DINOSAUR |     86 |     115.2720 |
| ACE GOLDFINGER   |     48 |     115.2720 |
| ADAPTATION HOLES |     50 |     115.2720 |
+------------------+--------+--------------+
3 rows in set (0.00 sec)
```

서브쿼리는 한 번 실행되고 그 답이 열을 따라 복사되는데, 비교 대상 값을 행 옆에 나란히 보여주는 방법이 이것입니다.

### 목록을 반환하는 서브쿼리

[IN](https://villagesql.com/docs/ko/tutorial/in.md)에 공급하는 서브쿼리는 많은 행을 반환해도 되는데, `IN`은 값이 아니라 목록을 기대하기 때문입니다.

```sql theme={null}
SELECT first_name, last_name
FROM actor
WHERE actor_id IN (SELECT actor_id FROM film_actor WHERE film_id = 1)
ORDER BY last_name
LIMIT 5;
```

```text theme={null}
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| JOHNNY     | CAGE      |
| ROCK       | DUKAKIS   |
| CHRISTIAN  | GABLE     |
| PENELOPE   | GUINESS   |
| MARY       | KEITEL    |
+------------+-----------+
5 rows in set (0.00 sec)
```

안쪽 쿼리는 영화 1에 출연한 모든 사람의 id를 반환하고, `IN`은 각 배우를 그 목록 전체와 대조합니다.

## ERROR 1242는 서브쿼리가 너무 많은 행을 반환했다는 뜻입니다

`=`는 1개의 것을 1개의 것과 비교합니다. 1,000개의 행을 반환하는 서브쿼리를 주면 서버는 더 진행할 수 없습니다.

```sql theme={null}
SELECT title FROM film WHERE length = (SELECT length FROM film);
```

```text theme={null}
ERROR 1242 (21000): Subquery returns more than 1 row
```

의도에 따라 3가지 해결책이 있습니다:

* 목록을 원했다면 `=` 대신 `IN`을 쓰세요.
* 집합에서 1개의 값을 원했다면 `MAX()` 같은 집계를 추가하세요.
* 아무 행 1개면 되고 `ORDER BY`로 어떤 행인지 말할 수 있다면 `LIMIT 1`을 추가하세요.

`ERROR 1242`는 적어도 소리 내어 실패합니다. 이 실수의 조용한 버전은 서브쿼리가 행을 하나도 반환하지 않는 것입니다: 그러면 NULL이 나오고, 비교도 NULL이 되며, 바깥 쿼리는 아무 말 없이 아무것도 반환하지 않습니다.

## 요약

* 한 쿼리의 답을 다른 쿼리에 공급하려면 서브쿼리를 쓰세요.
* 1개의 행과 1개의 열을 반환하는 스칼라 서브쿼리는 값처럼 동작한다고 예상하세요.
* `ERROR 1242`는 많은 행을 반환한 서브쿼리에 `=`를 쓴 것으로 읽으세요.
* 서브쿼리가 목록을 반환할 때는 `=` 대신 `IN`을 쓰세요.
* 바깥 쿼리가 오류 없이 아무것도 반환하지 않으면 빈 서브쿼리를 의심하세요.

## 함께 보기

* [상관 서브쿼리](https://villagesql.com/docs/ko/tutorial/correlated-subqueries.md) — 바깥 행을 읽는 서브쿼리
* [IN](https://villagesql.com/docs/ko/tutorial/in.md) — 서브쿼리에서 목록을 받는 연산자
* [파생 테이블](https://villagesql.com/docs/ko/tutorial/derived-tables.md) — 테이블로 쓰이는 서브쿼리
* [MySQL의 서브쿼리 대 JOIN](https://villagesql.com/docs/ko/guides/subqueries-vs-joins.md) — 어떤 형태를 고를지, 그리고 각각의 비용


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