> ## 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 AND, OR, NOT

> MySQL WHERE 절에서 AND, OR, NOT으로 조건을 결합하는 방법, 어느 것이 더 강하게 결합하는지, 그리고 조용히 잘못된 행을 반환하는 2가지 실수입니다.

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

조건 1개는 질문 1개에 답합니다. `AND`, `OR`, `NOT`은 조건을 서로 연결해서, `WHERE` 하나로 복합 질문을 할 수 있게 합니다.

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

## AND, OR, NOT의 동작 방식

```sql theme={null}
SELECT COLUMN_LIST
FROM TABLE_NAME
WHERE FIRST_CONDITION AND SECOND_CONDITION;
```

`COLUMN_LIST`를 원하는 열로, `TABLE_NAME`을 테이블로, `FIRST_CONDITION`과 `SECOND_CONDITION` 각각을 별도의 검사로 바꾸세요.

`AND`는 두 조건이 모두 참일 때만 행을 유지합니다. `OR`는 적어도 하나가 참일 때 행을 유지합니다. `NOT`은 뒤따르는 조건을 뒤집습니다.

셋은 똑같은 세기로 결합하지 않습니다. 3개 중 `NOT`이 가장 강하게 결합하고, 그다음이 `AND`, 그다음이 `OR`입니다. 따라서 서버는 `a OR b AND c`를 `a OR (b AND c)`로 읽는데, 그것을 쓴 사람이 의도한 뜻인 경우는 드뭅니다. 괄호가 그것에 우선하고, 괄호에는 비용이 들지 않습니다.

셋 모두 비교보다 느슨하게 결합하므로, 아래의 `NOT rating = 'G'`는 열만이 아니라 비교 전체를 뒤집습니다.

## 예제

### 두 조건 모두

```sql theme={null}
SELECT title, rating, length
FROM film
WHERE rating = 'G' AND length > 180
ORDER BY title;
```

```text theme={null}
+-----------------+--------+--------+
| title           | rating | length |
+-----------------+--------+--------+
| BAKED CLEOPATRA | G      |    182 |
| CATCH AMISTAD   | G      |    183 |
| CONTROL ANTHEM  | G      |    185 |
| DARN FORRESTER  | G      |    185 |
| INTRIGUE WORST  | G      |    181 |
| LAWLESS VISION  | G      |    181 |
| MOONWALKER FOOL | G      |    184 |
| MUSCLE BRIGHT   | G      |    185 |
| YOUNG LANGUAGE  | G      |    183 |
+-----------------+--------+--------+
9 rows in set (0.00 sec)
```

9편의 영화가 `G` 등급이면서 180분을 넘습니다.

### 둘 중 하나의 조건

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating = 'G' OR rating = 'PG'
ORDER BY title
LIMIT 5;
```

```text theme={null}
+------------------+--------+
| title            | rating |
+------------------+--------+
| ACADEMY DINOSAUR | PG     |
| ACE GOLDFINGER   | G      |
| AFFAIR PREJUDICE | G      |
| AFRICAN EGG      | G      |
| AGENT TRUMAN     | PG     |
+------------------+--------+
5 rows in set (0.00 sec)
```

한 열을 값 목록과 비교하는 일은 전용 연산자가 있을 만큼 흔합니다. [IN](https://villagesql.com/docs/ko/tutorial/in.md)은 같은 필터를 절 하나로 씁니다.

### 조건 뒤집기

```sql theme={null}
SELECT title, rating
FROM film
WHERE NOT rating = 'G'
ORDER BY title
LIMIT 5;
```

```text theme={null}
+------------------+--------+
| title            | rating |
+------------------+--------+
| ACADEMY DINOSAUR | PG     |
| ADAPTATION HOLES | NC-17  |
| AGENT TRUMAN     | PG     |
| AIRPLANE SIERRA  | PG-13  |
| AIRPORT POLLOCK  | R      |
+------------------+--------+
5 rows in set (0.00 sec)
```

`NOT rating = 'G'`와 `rating <> 'G'`는 같은 행을 선택합니다. 비교 하나에는 `<>`를 쓰고, `NOT`은 더 큰 것을 뒤집을 때를 위해 남겨 두세요.

## AND는 OR보다 강하게 결합합니다

이것은 "G 또는 PG 등급이고, 180분 초과"처럼 보입니다.

```sql theme={null}
SELECT title, rating, length
FROM film
WHERE rating = 'G' OR rating = 'PG' AND length > 180
ORDER BY title;
```

```text theme={null}
+---------------------------+--------+--------+
| title                     | rating | length |
+---------------------------+--------+--------+
| ACE GOLDFINGER            | G      |     48 |
| AFFAIR PREJUDICE          | G      |    117 |
| AFRICAN EGG               | G      |    130 |
...
+---------------------------+--------+--------+
182 rows in set (0.00 sec)
```

182개의 행이고, 첫 번째 행은 48분짜리입니다. `AND`가 바로 옆의 쌍에 결합했으므로, 서버는 "G 등급이거나, 아니면 PG 등급이고 180분 초과"에 답했습니다. 모든 `G` 영화가 길이와 상관없이 첫 번째 가지만으로 조건을 만족했습니다.

괄호가 의도한 바를 말해 줍니다.

```sql theme={null}
SELECT title, rating, length
FROM film
WHERE (rating = 'G' OR rating = 'PG') AND length > 180
ORDER BY title;
```

```text theme={null}
+-----------------+--------+--------+
| title           | rating | length |
+-----------------+--------+--------+
| BAKED CLEOPATRA | G      |    182 |
| CATCH AMISTAD   | G      |    183 |
| CONTROL ANTHEM  | G      |    185 |
| DARN FORRESTER  | G      |    185 |
| INTRIGUE WORST  | G      |    181 |
| LAWLESS VISION  | G      |    181 |
| MONSOON CAUSE   | PG     |    182 |
| MOONWALKER FOOL | G      |    184 |
| MUSCLE BRIGHT   | G      |    185 |
| RECORDS ZORRO   | PG     |    182 |
| STAR OPERATION  | PG     |    181 |
| WORST BANGER    | PG     |    185 |
| YOUNG LANGUAGE  | G      |    183 |
+-----------------+--------+--------+
13 rows in set (0.01 sec)
```

13개의 행입니다. 두 쿼리 모두 잘못된 쿼리가 아니고 아무것도 경고하지 않으므로, 유일한 방어책은 `AND`와 `OR`가 섞인 모든 조건을 쓰는 순간에 괄호로 묶는 것입니다.

## OR는 홀로 놓인 두 번째 값을 받지 않습니다

`rating = 'G' OR 'PG'`는 우리말로 "G 또는 PG 등급"으로 읽힙니다. 서버에게 그것은 2개의 별도 조건이고, 두 번째는 홀로 서 있는 문자열 `'PG'`입니다.

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating = 'G' OR 'PG'
ORDER BY title
LIMIT 5;
```

```text theme={null}
+-------------------+--------+
| title             | rating |
+-------------------+--------+
| ACE GOLDFINGER    | G      |
| AFFAIR PREJUDICE  | G      |
| AFRICAN EGG       | G      |
| ALAMO VIDEOTAPE   | G      |
| AMISTAD MIDSUMMER | G      |
+-------------------+--------+
5 rows in set, 1 warning (0.00 sec)
```

`G` 영화만 돌아왔고, 출력 하단이 경고 1개를 보고합니다. 같은 세션에서 `SHOW WARNINGS`를 실행하면 서버가 스스로 설명합니다:
`Warning 1292 Truncated incorrect DOUBLE value: 'PG'`.

조건은 참이거나 거짓이어야 하므로, 서버는 `'PG'`를 숫자로 변환했습니다. `'PG'`는 숫자로 시작하지 않으므로 0으로 변환되고, 0은 거짓입니다. 따라서 두 번째 가지 전체가 죽어 있었습니다. 양쪽에 열 이름을 쓰거나, [IN](https://villagesql.com/docs/ko/tutorial/in.md)을 사용하세요.

## NOT은 바로 다음 것만 뒤집습니다

```sql theme={null}
SELECT title, rating, length
FROM film
WHERE NOT rating = 'G' AND length > 180
ORDER BY title;
```

```text theme={null}
+--------------------+--------+--------+
| title              | rating | length |
+--------------------+--------+--------+
| ANALYZE HOOSIERS   | R      |    181 |
| CHICAGO NORTH      | PG-13  |    185 |
| CONSPIRACY SPIRIT  | PG-13  |    184 |
...
+--------------------+--------+--------+
30 rows in set (0.00 sec)
```

`NOT`은 바로 옆의 비교를 가져갔으므로, 이것은 "G 등급이 아니고, 180분 초과"입니다. 쌍 전체를 뒤집으려면 괄호로 묶으세요.

```sql theme={null}
SELECT title, rating, length
FROM film
WHERE NOT (rating = 'G' AND length > 180)
ORDER BY title
LIMIT 5;
```

```text theme={null}
+------------------+--------+--------+
| title            | rating | length |
+------------------+--------+--------+
| ACADEMY DINOSAUR | PG     |     86 |
| ACE GOLDFINGER   | G      |     48 |
| ADAPTATION HOLES | NC-17  |     50 |
| AFFAIR PREJUDICE | G      |    117 |
| AFRICAN EGG      | G      |    130 |
+------------------+--------+--------+
5 rows in set (0.00 sec)
```

`ACE GOLDFINGER`는 `G` 등급이고 48분짜리입니다. 괄호 안의 쌍을 만족하지 못하므로, 쌍을 뒤집으면 유지됩니다.

## 요약

* 모든 조건이 성립해야 할 때는 `AND`를, 하나만 성립하면 될 때는 `OR`를 사용하세요.
* `AND`가 더 강하게 결합하므로, `AND`와 `OR`가 섞인 모든 `WHERE`를 괄호로 묶으세요.
* `NOT`은 바로 옆의 조건만 뒤집는다고 예상하세요.
* 홀로 선 값은 숫자로 변환되므로, `OR`의 양쪽에 열 이름을 반복하세요.
* 출력 하단의 경고 개수를 살핀 다음 `SHOW WARNINGS`를 실행하세요.

## 함께 보기

* [WHERE](https://villagesql.com/docs/ko/tutorial/where.md) — 이 연산자들이 쌓아 올리는 절
* [IN](https://villagesql.com/docs/ko/tutorial/in.md) — 한 열을 여러 값과 비교하는 더 깔끔한 방법
* [연산자](https://villagesql.com/docs/ko/tutorial/operators.md) — 결합되는 비교들


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