REDUCE
REDUCE
REDUCE 함수는 람다 표현식(lambda expression)의 논리에 따라 배열(array)을 단일 값으로 축소해요.
REDUCE 함수는 배열, 초기 누산기(accumulator) 값, 그리고 람다 함수를 받아요. 배열의 각 요소에 람다 함수를 적용하며 각 결과로 누산기를 갱신해요. 모든 요소를 처리한 후 REDUCE는 최종 누산기 값을 반환해요.
참고: Snowflake 고차 함수를 사용해 데이터에서 람다 함수 사용하기를 참조하세요.
출처: 문서
본문
문법 (Syntax)
REDUCE( <array> , <init> , <lambda_expression> )
인자 (Arguments)
- array — 축소할 요소를 담은 배열이에요. 배열은 반구조화(semi-structured) 또는 구조화(structured)일 수 있어요.
- init — 초기 누산기 값이에요.
- lambda_expression — 각 배열 요소에 대한 축소 논리를 정의하는 람다 표현식이에요. 람다 표현식은 다음 구문으로 지정해야 해요:
<acc> [ <datatype> ] , <value> [ <datatype> ] -> <expr>acc인자는 누산기이고,value인자는 배열에서 현재 처리 중인 요소예요.
반환 (Returns)
이 함수는 모든 데이터 타입의 값을 반환할 수 있어요.
입력 배열이 비어 있으면 함수는 누산기의 초기 값을 반환해요.
함수는 다음 경우에 NULL을 반환해요:
- 입력 배열이 NULL일 때.
- 누산기의 초기 값이 NULL일 때.
- 람다 함수가 NULL을 반환할 때.
사용 메모 (Usage notes)
- 람다 값 인자에 대한 데이터 타입을 명시적으로 지정하면, 람다 호출 전에 배열 요소가 지정된 타입으로 강제 변환(coerce)돼요. 변환에 대한 자세한 내용은 데이터 타입 변환(Data type conversion)을 참조하세요.
- 타입 검사는 누산기의 초기 값, 누산기 람다 인자, 람다 실행의 반환 값이 모두 동일한 논리 타입과 물리 타입을 가지도록 강제해요. 이 요구 사항을 충족하기 위해 캐스팅을 사용하면 세 가지 중 가장 큰 물리 타입이 사용돼요.
- value 인자는 중간 중간 NULL 값을 가질 수 있어요. 예제는 배열의 NULL 값 건너뛰기(Skip NULL values in an array)를 참조하세요.
예제 (Examples)
다음 예제들은 REDUCE 함수를 사용해요.
배열의 값 합 계산하기
REDUCE 함수를 사용해 배열의 값 합을 반환하고 초기 누산기 값을 0으로 지정해요:
SELECT REDUCE([1,2,3],
0,
(acc, val) -> acc + val
) AS sum_of_values;
+---------------+
| SUM_OF_VALUES |
|---------------|
| 6 |
+---------------+
이 예제는 이전 예제와 같지만 INT 유형의 구조화된 배열을 지정해요:
SELECT REDUCE([1,2,3]::ARRAY(INT),
0,
(acc, val) -> acc + val
) AS sum_of_values_structured;
+--------------------------+
| SUM_OF_VALUES_STRUCTURED |
|--------------------------|
| 6 |
+--------------------------+
REDUCE 함수를 사용해 배열의 값 합을 반환하고 초기 누산기 값을 10으로 지정해요:
SELECT REDUCE([1,2,3],
10,
(acc, val) -> acc + val
) AS sum_of_values_plus_10;
+-----------------------+
| SUM_OF_VALUES_PLUS_10 |
|-----------------------|
| 16 |
+-----------------------+
배열의 각 값 제곱 합 계산하기
REDUCE 함수를 사용해 배열의 각 값 제곱의 합을 반환하고 초기 누산기 값을 0으로 지정해요:
SELECT REDUCE([1,2,3],
0,
(acc, val) -> acc + val * val
) AS sum_of_squares;
+----------------+
| SUM_OF_SQUARES |
|----------------|
| 14 |
+----------------+
배열의 NULL 값 건너뛰기
이 예제에서 배열 인자는 NULL 값을 포함해요. 이 배열을 REDUCE 함수에 전달하면 누산기는 중간 중간 NULL 값을 갖게 돼요.
REDUCE 함수를 사용해 배열의 값 합을 반환하고, 람다 표현식의 논리에서 ZEROIFNULL 함수를 사용해 배열의 NULL 값을 건너뛰어요. 람다 표현식은 ZEROIFNULL 함수를 사용해 배열의 각 값을 다음 논리로 처리해요:
- val이 NULL이면 람다 표현식의 결과는
acc + 0이에요. - val이 NULL이 아니면 람다 표현식의 결과는
acc + val이에요.
쿼리를 실행해요:
SELECT REDUCE([1,NULL,2,NULL,3,4],
0,
(acc, val) -> acc + ZEROIFNULL(val))
AS sum_of_values_skip_null;
+-------------------------+
| SUM_OF_VALUES_SKIP_NULL |
|-------------------------|
| 10 |
+-------------------------+
문자열 값 생성하기
REDUCE 함수를 사용해 배열의 각 값을 연결해 문자열 값 목록을 반환해요:
SELECT REDUCE(['a', 'b', 'c'],
'',
(acc, val) -> acc || ' ' || val
) AS string_values;
+---------------+
| STRING_VALUES |
|---------------|
| a b c |
+---------------+
누산기에 배열 사용하기
REDUCE 함수를 람다 표현식의 논리에서 ARRAY_PREPEND 함수와 함께 사용해 입력 배열의 순서를 뒤집은 배열을 반환해요:
SELECT REDUCE([1, 2, 3, 4],
[],
(acc, val) -> ARRAY_PREPEND(acc, val)
) AS reverse_order;
+---------------+
| REVERSE_ORDER |
|---------------|
| [ |
| 4, |
| 3, |
| 2, |
| 1 |
| ] |
+---------------+
조건부 논리 사용하기
REDUCE 함수를 람다 표현식의 논리에서 IFF 함수와 함께 사용해 if-then 표현식과 유사한 조건부 논리를 기반으로 작업을 수행해요. 이 예제는 람다 표현식에 다음 논리를 사용해요:
- 배열 값이 7보다 작으면 제곱해서 누산기에 더해요.
- 배열 값이 7보다 크거나 같으면 제곱하지 않고 누산기에 더해요.
SELECT REDUCE([5,10,15],
0,
(acc, val) -> IFF(val < 7, acc + val * val, acc + val)
) AS conditional_logic;
+-------------------+
| CONDITIONAL_LOGIC |
|-------------------|
| 50 |
+-------------------+
테이블의 배열 요소를 단일 값으로 축소하기
order_id, order_date, order_detail 열을 가진 orders라는 테이블이 있다고 가정해요. order_detail 열은 라인 항목, 구매 수량, 소계(subtotal)의 배열이에요. 테이블에는 두 행의 데이터가 있어요. 다음 SQL 문은 이 테이블을 만들고 행을 삽입해요:
CREATE OR REPLACE TABLE orders AS
SELECT 1 AS order_id, '2024-01-01' AS order_date, [
{'item':'UHD Monitor', 'quantity':3, 'subtotal':1500},
{'item':'Business Printer', 'quantity':1, 'subtotal':1200}
] AS order_detail
UNION
SELECT 2 AS order_id, '2024-01-02' AS order_date, [
{'item':'Laptop', 'quantity':5, 'subtotal':7500},
{'item':'Noise-canceling Headphones', 'quantity':5, 'subtotal':1000}
] AS order_detail;
SELECT * FROM orders;
+----------+------------+-------------------------------------------+
| ORDER_ID | ORDER_DATE | ORDER_DETAIL |
|----------+------------+-------------------------------------------|
| 1 | 2024-01-01 | [ |
| | | { |
| | | "item": "UHD Monitor", |
| | | "quantity": 3, |
| | | "subtotal": 1500 |
| | | }, |
| | | { |
| | | "item": "Business Printer", |
| | | "quantity": 1, |
| | | "subtotal": 1200 |
| | | } |
| | | ] |
| 2 | 2024-01-02 | [ |
| | | { |
| | | "item": "Laptop", |
| | | "quantity": 5, |
| | | "subtotal": 7500 |
| | | }, |
| | | { |
| | | "item": "Noise-canceling Headphones", |
| | | "quantity": 5, |
| | | "subtotal": 1000 |
| | | } |
| | | ] |
+----------+------------+-------------------------------------------+
REDUCE 함수를 사용해 각 주문의 모든 항목에 대한 소계 합을 반환해요:
SELECT order_id,
order_date,
REDUCE(o.order_detail,
0,
(acc, val) -> acc + val:subtotal
) AS subtotal_sum
FROM orders o;
+----------+------------+--------------+
| ORDER_ID | ORDER_DATE | SUBTOTAL_SUM |
|----------+------------+--------------|
| 1 | 2024-01-01 | 2700 |
| 2 | 2024-01-02 | 8500 |
+----------+------------+--------------+
REDUCE 함수를 사용해 각 주문에서 판매된 항목의 목록을 반환해요:
SELECT order_id,
order_date,
REDUCE(o.order_detail,
'',
(acc, val) -> val:item || '\n' || acc
) AS items_sold
FROM orders o;
+----------+------------+-----------------------------+
| ORDER_ID | ORDER_DATE | ITEMS_SOLD |
|----------+------------+-----------------------------|
| 1 | 2024-01-01 | Business Printer |
| | | UHD Monitor |
| | | |
| 2 | 2024-01-02 | Noise-canceling Headphones |
| | | Laptop |
| | | |
+----------+------------+-----------------------------+
람다 표현식에서 테이블 열을 참조해 테이블 데이터의 배열 요소 축소하기
ARRAY 유형의 열 하나와 INT 유형의 열 하나가 있는 테이블을 만들어요:
CREATE OR REPLACE TABLE reduce_column_ref_demo AS
SELECT [ 1, 2, 3 ] AS col1, 0 AS col2
UNION
SELECT [ 1, 2, 3 ] AS col1, 10 AS col2;
SELECT * FROM reduce_column_ref_demo;
+------+------+
| COL1 | COL2 |
|------+------|
| [ | 0 |
| 1, | |
| 2, | |
| 3 | |
| ] | |
| [ | 10 |
| 1, | |
| 2, | |
| 3 | |
| ] | |
+------+------+
REDUCE 함수를 사용해 col2 값을 누산기 값에 더해 각 행의 배열 값 합을 반환해요:
SELECT REDUCE(col1,
10,
(acc, val) -> (acc + col2) + val
) AS reduce_col_ref
FROM reduce_column_ref_demo;
+----------------+
| REDUCE_COL_REF |
|----------------|
| 16 |
| 46 |
+----------------+