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 |
+----------------+

더 알아보기 (Learn more)