# 12강. 수치 연산
**`산술연산`**
```
+ - * / % MOD
```

- 어떤 계산을 할지는 연산자를 이용해 지정한다.
- `WHERE` 구에서 조건을 지정할 때 사용했던 `=` 역시 연산자의 하나이다.

## 1. 사칙연산
- 덧셈, 뺄셈, 곱셈, 나눗셈의 사칙 연산과 나눗셈의 나머지

|연산자|연산|예|
|-|-|-|
|+|덧셈(가산)|1+2 -> 3|
|-|뺄셈(감산)|1-2 -> -1|
|\*|곱셈(승산)|1*2 -> 2|
|/|나눗셈(제산)|1/2 -> 0.5|
|%|나머지|1%2 -> 1|

- 곱셈은 `x` 기호를 사용하지만 컴퓨터 언어에서는 `x` 기호가 존재하지 않아 대신 `애스터리스크(*)`를 사용한다.
- `*`는 `모든 열`을 의미하는 메타 문자이지만 연산자로도 사용할 수 있다.
- 컴퓨터 언어에서는 나눗셈 기호로 `슬래시(/)`를 사용한다.
- 나머지는 나눗셈을 한 후의 나머지를 계산하는 것으로 `%` 기호를 사용한다.
- 나머지 연산의 결과는 몫이 정수값이 되도록 계산하는 것이 특징이다.
- 제품에 따라서는 `%` 대신 `MOD` 함수를 사용하는 경우도 있다.

##### 연산자를 사용해 여러 가지 연산을 할 수 있다!

### 연산자의 우선순위
|우선순위|연산자|
|-|-|
|1|* / % |
|2|+ -|

- 곱셈, 나눗셈, 나머지 그룹과 덧셈, 뺄셈 그룹으로 나뉜다.
- 같은 그룹 내 연산자의 우선 순위는 동일하다.
- 계산 순서는 연산자에 따라 관계없는 경우도 있지만 기본적으로 왼쪽에서 오른쪽으로 진행된다.
- 우선순위가 같은 연산자들끼리 연산하는 경우는 문제가 되지 않지만 우선순위가 다른 연산자들이 섞여있는 경우는 우선순위가 높은 쪽이 먼저 계산된다.
- `SQL` 명령에서는 여러 부분에서 산술 연산자를 사용해 연산할 수 있다.
- `SELECT` 구나 `WHERE` 구 안에서도 연산할 수 있다.

---

## 2. SELECT 구로 연산하기
- `SELECT` 구에는 열명 외에도 여러 가지 식을 기술할 수 있다. 
- 이때의 식은 열명, 연산자, 상수로 구성된다.

**`SELECT 구`**
```
SELECT 식 1, 식 2 ... FROM 테이블명
```

- 식을 기술할 수 있다는 건 명령이 실행될 때 연산을 할 수 있다는 것을 의미한다.

```
SELECT *, price * quantity FROM sample34;
```

---

## 3. 열의 별명
- 만약 열 이름이 길고 알아보기 어려운 경우는 별명을 붙여 열명을 재지정할 수 있다.

**`SELECT 구에서 식에 별명 붙이기`**
```
SELECT *, price * quantity AS amount FROM sample34;
```

- 별명은 `예약어(AS)`를 사용해 지정한다.
- `SELECT` 구에서는 `콤마(,)`로 구분해 복수의 식을 지정할 수 있으며, 각각의 식에 별명을 붙일 수 있다.
- 별명을 지정할 때는 기본적으로 중복되지 않게 지정해야 한다(프로그래밍 언어에서 결괏값의 처리 방식에 따라 문제가 발생할 수 있다).
- 키워드 `AS`는 생략할 수 있다. `SELECT price * quantity amount`라고 써도 무방하다.
- `에일리어스(alias)`라고도 불리는 별명은 영어, 숫자, 한글 등으로 지정할 수 있다.
- 단, 별명을 한글로 지정하는 경우에는 여러 가지로 오작동하는 경우가 많으므로 `더블쿼트(MySQL에서는 백쿼트)`로 둘러싸서 지정한다.
- 이 룰은 데이터베이스 객체의 이름에 `ASCII` 문자 이외의 것을 사용할 경우에 해당한다.

```
SELECT price * quantity "금액" FROM sample34;
```

##### 이름에 ASCII 문자 이외의 것을 포함할 경우는 더블쿼트로 둘러싸서 지정한다!

- 더블쿼트로 둘러싸면 명령구문을 분석할 때 데이터베이스 객체의 이름이라고 간주한다.
- 싱글쿼트로 둘러싸는 것은 문자열 상수이다.
- 별명을 `예약어와 같은 이름은 지정할 수 없다`고 했지만 더블쿼트로 둘러싸서 지정하면 사용할 수 있다.

```
SELECT price * quantity AS "SELECT" FROM sample34;
```

- 이름을 붙일 때는 숫자로 시작할 수 없다.
- 수치형 상수를 명령 안에서 사용할 경우에는 쿼트로 묶지 않고 숫자만 입력한다.
- 이때 이름이 숫자로 시작한다면 그것이 수치형 상수를 의미하는 것인지 데이터베이스 객체명을 의미하는 것인지 구별할 수 없다.
- 그에 따라 데이터베이스 객체명은 `숫자로 시작해서는 안 된다.`
- 물론 이름이 예약어와 겹칠 때와 마찬가지로 더블쿼트로 묶으면 피할 수 있다.
- `MySQL`에서는 숫자로 시작하는 객체명이 허용된다.
- 다만 숫자만으로 구성되는 객체명은 허용되지 않는다.
- 한편 `Oracle`에서는 숫자로 시작하는 이름은 허용되지 않는다.
- 더블쿼트로 둘러싸면 객체명으로 간주하는 룰은 표준 SQL에 규정되어 있다.

##### 이름을 지정하는 경우 숫자로 시작되지 않도록 한다!

---

## 4. WHERE 구에서 연산하기
- `SELECT` 구에 이어, 지금부터는 `WHERE` 구에서의 연산 또한 가능하다.
- `WHERE` 구의 조건식은 `price * quantity`일 때, `price * quantity`로 금액을 계산해 그 값이 2000 이상인 행을 검색하라는 뜻이다.
- 여기서 `price * quantity`를 계산할 때 `SELECT` 구에서 `amount`라는 별명을 붙였으므로 `WHERE` 구에도 `amount`로 지정하면 될 것 같지만 실제로 `SELECT` 명령을 실행해보면 `amount`라는 열은 존재하지 않는다는 에러가 발생한다.

```
SELECT *, price * quantity AS amount FROM sample34
WHERE amount >= 2000;
```

### WHERE 구와 SELECT 구의 내부처리 순서
- `WHERE` 구에서의 행 선택, `SELECT` 구에서의 열 선택은 데이터베이스 서버 내부에서 `WHERE 구 -> SELECT 구`의 순서로 처리된다.
- 표준 SQL에는 내부 처리 순서가 따로 정해져있지 않다. 하지만 `WHERE 구 -> SELECT 구` 순서로 내부처리를 하는 데이터베이스가 많다.
- 따라서 `WHERE` 구로 행이 조건에 일치하는지 아닌지를 먼저 조사한 후에 `SELECT` 구에 지정된 열을 선택해 결과로 반환하는 식으로 처리한다.
- 별명은 `SELECT` 구문을 내부 처리할 때 비로소 붙여진다.
- 즉, `WHERE` 구의 처리는 `SELECT` 구보다 선행되므로 `WHERE` 구에서 사용한 별칭은 아직 내부적으로 지정되지 않은 상태가 되어 에러가 발생하는 것이다.

##### SELECT 구에서 지정한 별명은 WHERE 구 안에서 사용할 수 없다!

---

## 5. NULL 값의 연산
- `NULL` 값을 이용해 `NULL + 1`과 같은 연산을 하면 어떻게 될까요?
- SQL에서는 `NULL` 값이 0으로 처리되지 않는다.
- 즉, `NULL + 1`의 결괏값은 1이 아닌 `NULL`이다.
- 나눗셈을 할때도 `NULL`이 0으로 처리되지 않는다는 것을 알 수 있다.
- 따라서 `1 / NULL`을 계산해도 `NULL`이 0으로 처리되지 않아 에러가 발생하지 않고 결과는 `NULL`이 된다.

##### NULL로 연산하면 결과는 NULL이 된다!

---

## 6. ORDER BY 구에서 연산하기
- `ORDER BY` 구에서도 연산할 수 있고 그 결괏값들을 정렬할 수 있다.

```
SELECT *, price * quantity AS amount FROM sample34 ORDER BY price * quantity DESC;
```

- 위 명령어를 실행하면 `amount` 값이 내림차순으로 정렬된다.
- `ORDER BY`는 서버에서 내부적으로 가장 나중에 처리된다.
- 즉, `SELECT` 구보다 나중에 처리되기 때문에 `SELECT` 구에서 지정한 별명을 `ORDER BY`에서도 사용할 수 있다.

```
WHERE 구 -> SELECT 구 -> ORDER BY 구
```

##### ORDER BY 구에서는 SELECT 구에서 지정한 별명을 사용할 수 있다!

---

## 7. 함수
- 연산자 외에 함수를 사용해 연산할 수도 있다.
- 함수는 다음과 같은 문법으로 표기한다.

**`함수`**
```
함수명 (인수1, 인수2 ...)
```

- 연산자는 기호에 따라 연산 방법이 결정된다. 한편 함수는 함수명에 따라 연산 방법이 결정된다.
- 연산자는 좌우의 항목이 연산 대상이 된다.
- 함수는 계산 대상을 인수로 지정한다.
- 이때 인수는 함수명 뒤에 괄호로 묶어 표기한다.
- 인수의 수나 구분 방법은 함수에 따라 다르며, 대부분의 함수는 1개 이상의 인수를 가진다.
- 인수는 파라미터라고도 부르며, 연산자가 그러하듯 함수 역시 결괏값을 반환한다.
- 이를 `함수의 반환값`이라고 부른다.

```
10 % 3 -> 1
MOD(10, 3) -> 1
```

##### 함수도 연산자도 표기 방법이 다를 뿐, 같은 것이다!

---

## 8. ROUND 함수
- 반올림을 하는데 이때 사용되는 것이 `ROUND` 함수이다.

**`ROUND로 반올림하기`**
```
SELECT amount, ROUND(amount) FROM sample34;
```

- `INTEGER` 형의 경우는 정수밖에 저장할 수 없기 때문에 소수점이 포함되는 열은 `DECIMAL` 형으로 정의한다.
- `DECIMAL` 형은 열을 정의할 때 정수부와 소수부의 자릿수를 지정할 수 있는 자료형이다. 다시 말해 소수점을 포함하는 수치를 저장하는 자료형이다.

### 반올림 자릿수 지정
- `ROUND` 함수는 기본적으로 소수점 첫째 자리를 기준으로 반올림한 값을 반환한다.
- 이때 `ROUND` 함수의 두 번째 인수로 반올림할 자릿수를 지정할 수 있다.
- 해당 인수를 생략하는 경우는 0으로 간주되어, 소수점 첫째 자리를 반올림한다. 1을 지정하면 소수점 둘째 자리를 반올림한다.

```
SELECT amount, ROUND(amount, 1) FROM sample341;
```

- 음수로 지정해 정수부의 반올림할 자릿수도 지정할 수 있다.
- `-1`을 지정하면 1단위, `-2`를 지정하면 10단위를 반올림할 수 있다.
- 그 밖에도 반올림 외에 `버림`을 하는 경우도 있는데 이는 `TRUNCATE` 함수로 계산할 수 있다.
- 이 외에도 다양한 함수가 존재한다(`SIN`, `COS`, `SQRT`, `LOG`, `SUM` 등).

---