산술 연산자
산술 연산자 (Arithmetic operators)
이 문서는 Snowflake의 산술 연산자와, 산술 연산 결과의 scale과 precision이 어떻게 결정되는지 설명해요. 곱셈, 나눗셈, 덧셈·뺄셈, 비트 연산까지 각 연산별 자릿수 계산 규칙을 자세히 다루어요.
본문
산술 연산자는 하나 이상의 입력 표현식에서 숫자 출력을 생성하는 데 사용해요.
입력 표현식은 다음 경우를 제외하고는 숫자(fixed-point 또는 floating-point)여야 해요:
- 단항 연산자
+는 숫자 문자열을 받을 수 있는데, 문자열은 대응하는 숫자 값으로 암시적으로 변환돼요. - 이항 연산자
-는 DATE 표현식에 적용될 수 있어요.
산술 연산자 목록
| Operator | Syntax | Description |
| + (unary) | +a | a를 반환하고, a를 숫자 값으로 암시적 변환해요. a가 문자열인데 숫자 값으로 변환될 수 없으면 오류가 반환돼요. |
| + | a + b | 두 숫자 표현식(a, b)을 더해요. |
| - (unary) | -a | 입력 숫자 표현식의 부호를 반전해요. |
| - | a - b | 한 숫자 표현식(b)을 다른 표현식(a)에서 빼요. |
| - | a - b | 한 날짜 표현식(b)을 다른 날짜 표현식(a)에서 빼요. 결과는 정수 일수예요. 뺄셈은 DATE 표현식에 허용되는 유일한 산술 연산이에요. |
| * | a * b | 두 숫자 표현식(a, b)을 곱해요. |
| / | a / b | 한 숫자 표현식(a)을 다른 표현식(b)으로 나눠요. 0으로 나누거나 NULL일 때 0을 반환하는 함수는 DIV0와 DIV0NULL을 참고하세요. |
| % | a % b | 숫자 표현식 a의 b에 대한 나머지를 계산해요. 자세한 내용은 MOD를 참고하세요. |
산술 연산에서의 scale과 precision
산술 연산 출력의 scale과 precision은 입력의 scale과 precision에 따라 달라져요.
Snowflake는 다양한 산술 연산(곱셈, 나눗셈 등)으로 생성되는 숫자 출력에서 scale과 precision을 보존하기 위해 계산을 사용해요. 이 섹션에서 사용되는 설명은 다음과 같아요:
- 선행 자릿수(Leading digits) — 숫자 값의 소수점 왼쪽에 있는 자릿수(
L)예요. - Scale — 숫자 값의 소수점 오른쪽에 있는 자릿수(
S)예요. - Precision — 숫자 값의 총 자릿수(
P)로, 선행 자릿수와 scale의 합으로 계산돼요 (즉P = L + S). Snowflake에서 precision은 항상 38로 제한되는 점에 유의하세요.
또한:
- Fixed-point 데이터 타입(NUMBER, DECIMAL 등)은 precision과 scale을 사용해요. 예를 들어 DECIMAL(8,2) 타입은 precision이 8, scale이 2, 선행 자릿수가 6이에요.
- Floating-point 데이터 타입(FLOAT, DOUBLE, REAL 등)은 8바이트 double을 사용해요.
출력의 경우 이 값들은 최대 자릿수에 유의하세요. 실제 특정 출력의 자릿수는 더 적을 수 있어요.
곱셈 (Multiplication)
곱셈을 수행할 때:
- 출력의 선행 자릿수는 두 입력의 선행 자릿수의 합이에요.
- Snowflake는 (연쇄적 곱셈으로 인한) 잠재적 오버플로를 줄이기 위해 두 입력의 scale 자릿수를 더하는데, 최대 12자리까지예요. 단, 입력 중 하나의 scale이 12보다 크면 더 큰 입력 scale이 출력 scale로 사용돼요.
즉, 두 입력(L1.S1, L2.S2)이 있는 곱셈 연산을 가정하면 출력의 최대 자릿수는 다음과 같이 계산돼요:
Leading digits: L = L1 + L2
Scale: S = min(S1 + S2, max(S1, S2, 12))
Precision: P = L + S
참고: Snowflake는 숫자 값에 대해 정수 곱셈을 수행하므로 중간 결과에서 일부 오버플로가 발생할 수 있지만, 최종 출력은 오버플로되지 않아요.
예시
SELECT 10.01 n1, 1.1 n2, n1 * n2;
+-------+-----+---------+
| N1 | N2 | N1 * N2 |
|-------+-----+---------|
| 10.01 | 1.1 | 11.011 |
+-------+-----+---------+
SELECT 10.001 n1, .001 n2, n1 * n2;
+--------+-------+----------+
| I1 | I2 | I1 * I2 |
|--------+-------+----------|
| 10.001 | 0.001 | 0.010001 |
+--------+-------+----------+
SELECT .1 n1, .0000000000001 n2, n1 * n2;
+-----+-----------------+-----------------+
| N1 | N2 | N1 * N2 |
|-----+-----------------+-----------------|
| 0.1 | 0.0000000000001 | 0.0000000000000 |
+-----+-----------------+-----------------+
나눗셈 (Division)
나눗셈을 수행할 때:
- 출력의 선행 자릿수는 분자의 선행 자릿수와 분모의 scale의 합이에요.
- Snowflake는 (연쇄적 나눗셈으로 인한) 출력의 잠재적 오버플로와 scale 손실을 줄이기 위해 분자의 scale에 6자리를 더하는데, 최대 12자리까지예요. 단, 분자의 scale이 12보다 크면 분자 scale이 출력 scale로 사용돼요.
즉, 분자 L1.S1과 분모 L2.S2가 있는 나눗셈 연산을 가정하면 출력의 최대 자릿수는 다음과 같이 계산돼요:
Leading digits: L = L1 + S2
Scale: S = max(S1, min(S1 + 6, 12))
Precision: P = L + S
나눗셈 결과가 출력 scale을 초과하면 Snowflake는 출력을 버리지(truncate) 않고 반올림해요.
참고: 곱셈과 마찬가지로 중간 나눗셈 결과에서 일부 오버플로가 발생할 수 있지만, 최종 출력은 오버플로되지 않아요.
예시
SELECT 2 n1, 7 n2, n1 / n2;
+----+----+----------+
| N1 | N2 | N1 / N2 |
|----+----+----------|
| 2 | 7 | 0.285714 |
+----+----+----------+
SELECT 10.1 n1, 2.1 n2, n1 / n2;
+------+-----+-----------+
| N1 | N2 | N1 / N2 |
|------+-----+-----------|
| 10.1 | 2.1 | 4.8095238 |
+------+-----+-----------+
SELECT 10.001 n1, .001 n2, n1 / n2;
+--------+-------+-----------------+
| N1 | N2 | N1 / N2 |
|--------+-------+-----------------|
| 10.001 | 0.001 | 10001.000000000 |
+--------+-------+-----------------+
SELECT .1 n1, .0000000000001 n2, n1 / n2;
+-----+-----------------+-----------------------+
| N1 | N2 | N1 / N2 |
|-----+-----------------+-----------------------|
| 0.1 | 0.0000000000001 | 1000000000000.0000000 |
+-----+-----------------+-----------------------+
덧셈과 뺄셈 (Addition and subtraction)
덧셈 또는 뺄셈의 경우:
- 출력의 선행 자릿수는 입력 중 가장 큰 선행 자릿수에 1을 더한 값이에요 (올림(carry) 값을 보존하기 위해서).
- 출력의 scale은 입력 중 가장 큰 scale이에요.
즉, 두 입력(L1.S1, L2.S2)이 있는 덧셈 또는 뺄셈 연산을 가정하면 출력의 최대 자릿수는 다음과 같이 계산돼요:
Leading digits: L = max(L1, L2) + 1
Scale: S = max(S1, S2)
Precision: P = L + S
기타 N-ary 연산 (Other N-ary operations)
숫자 입력이 둘 이상인 다른 모든 산술 연산(예: modulo a % b 또는 MOD)의 경우:
- 출력의 선행 자릿수는 입력 중 가장 큰 선행 자릿수예요.
- 출력의 scale은 입력 중 가장 큰 scale이에요.
즉, 입력이 L1.S1, L2.S2 등인 n-ary 연산을 가정하면 출력의 최대 자릿수는 다음과 같이 계산돼요:
Leading digits: L = max(L1, L2, ...)
Scale: S = max(S1, S2, ...)
Precision: P = L + S
단항 연산 (Unary operations)
단항 산술 연산은 ROUND를 제외하고 입력과 동일한 출력 precision과 scale을 가져요. ROUND는 출력 scale을 명시적으로 지정할 수 있어요.
비트 연산 (Bitwise operations)
지원되는 비트 산술 연산 목록은 조건부 표현식 함수 문서에서 확인할 수 있어요.
참고:
- 숫자 값의 경우 비트 연산은 입력의 선행 자릿수에만 연산해요. 출력의 scale은 항상 0이에요.
- 이진 비트 연산의 경우 출력은 입력의 최대 선행 자릿수와 같은 수의 선행 자릿수를 가져요.