FIRST_VALUE

FIRST_VALUE

FIRST_VALUE()는 정렬된 값 그룹 내에서 첫 번째 값을 반환해요.

함께 보기:

LAST_VALUE , NTH_VALUE

출처: Snowflake SQL Reference

본문

문법

FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ]
  OVER ( [ PARTITION BY <expr1> ] ORDER BY <expr2>  [ { ASC | DESC } ] [ NULLS { FIRST | LAST } ] [ <window_frame> ] )

자세한 *window_frame* 문법은 창 함수 문법 및 사용(Window function syntax and usage)을 참고하세요.

인자

PARTITION BY column_1, column_2
ORDER BY column_3, column_4

expr

반환 값을 결정하는 표현식이에요.

expr1

행을 파티션으로 나누는 표현식이에요. 단일 표현식 또는 쉼표로 구분된 표현식 목록을 지정할 수 있어요. 예:

expr2

행을 정렬하는 표현식이에요. 단일 표현식 또는 쉼표로 구분된 표현식 목록을 지정할 수 있어요. 예:

{ IGNORE | RESPECT } NULLS

expr에 NULL 값이 포함될 때 NULL 값을 무시할지 존중할지 여부예요. IGNORE NULLS는 첫 번째 NULL이 아닌 값을 반환해요. RESPECT NULLS는 NULL 값이 표현식의 첫 번째 값이면 NULL 값을 반환해요. 기본값: RESPECT NULLS.

사용 지침

  • 이 함수는 순위 관련 함수이므로 창(window)을 지정해야 해요. 창 절은 다음 하위 절로 구성돼요.

    • PARTITION BY expr1 하위 절(선택).

    • ORDER BY expr2 하위 절(필수). 추가 지원 정렬 옵션(정렬 순서, NULL 값 정렬 등)에 대한 자세한 내용은 같은 규칙을 따르는 ORDER BY 절 문서를 참고하세요.

    • window_frame 하위 절(선택).

  • 창 안의 행 순서(따라서 쿼리 결과)는 ORDER BY 절의 키가 각 행을 고유하게 만들 때만 완전히 결정적이에요. 다음 예제를 고려해 보세요.

... OVER (PARTITION BY p ORDER BY o COLLATE 'lower') ...

어떤 파티션에 열 o의 값이 동일하거나 대소문자 비민감 비교에서 동일해질 값이 포함되면 쿼리 결과가 달라질 수 있어요.

  • OVER 절 안의 ORDER BY 절은 창 안에서만 행 순서를 제어할 뿐, 전체 쿼리 출력의 행 순서는 제어하지 않아요. 출력 순서를 제어하려면 쿼리의 가장 바깥쪽 수준에 별도의 ORDER BY 절을 사용하세요.

  • 선택적인 *window_frame*은 함수가 계산되는 창 내의 행 부분 집합을 지정해요. *window_frame*을 지정하지 않으면 기본값은 전체 창이에요.

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

이것은 창 프레임에 대해 다음 기본값을 지정하는 ANSI 표준에서 벗어난다는 점에 유의하세요.

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

자세한 *window_frame* 문법은 창 함수 문법 및 사용(Window function syntax and usage)을 참고하세요.

예제

이 예제는 각 카테고리에서 가장 저렴한 메뉴 항목을 찾기 위해 FIRST_VALUE 함수를 사용하는 쿼리를 보여줘요. 이 쿼리에는 두 개의 ORDER BY 절이 있어요. 하나는 각 파티션의 행 순서를 제어하고, 다른 하나는 전체 쿼리의 출력을 정렬해요. 이 예제에서 사용하는 테이블을 만들고 로드하려면 menu_items 테이블 만들기 및 로드를 참고하세요.

SELECT menu_category, menu_item_name, menu_price_usd,
       FIRST_VALUE(menu_item_name) OVER (PARTITION BY menu_category ORDER BY menu_price_usd) AS cheapest_item
  FROM menu_items
  WHERE menu_category IN ('Beverage', 'Dessert', 'Snack')
  ORDER BY menu_category, menu_price_usd
  LIMIT 12;
+---------------+--------------------+----------------+---------------+
| MENU_CATEGORY | MENU_ITEM_NAME     | MENU_PRICE_USD | CHEAPEST_ITEM |
|---------------+--------------------+----------------+---------------|
| Beverage      | Bottled Water      |           2.00 | Bottled Water |
| Beverage      | Iced Tea           |           3.00 | Bottled Water |
| Beverage      | Bottled Soda       |           3.00 | Bottled Water |
| Beverage      | Lemonade           |           3.50 | Bottled Water |
| Dessert       | Popsicle           |           3.00 | Popsicle      |
| Dessert       | Ice Cream Sandwich |           4.00 | Popsicle      |
| Dessert       | Mango Sticky Rice  |           5.00 | Popsicle      |
| Dessert       | Sugar Cone         |           6.00 | Popsicle      |
| Dessert       | Waffle Cone        |           6.00 | Popsicle      |
| Dessert       | Two Scoop Bowl     |           7.00 | Popsicle      |
| Snack         | Spring Mix Salad   |           6.00 | Fried Pickles |
| Snack         | Fried Pickles      |           6.00 | Fried Pickles |
+---------------+--------------------+----------------+---------------+

다음 예제는 menu_items 테이블을 사용해 세 가지 관련 함수, FIRST_VALUE, NTH_VALUE, LAST_VALUE를 비교해요.

  • 이 쿼리는 너비가 3개 행인 슬라이딩 창 프레임을 만들어요. 여기에는 다음이 포함돼요.

    • 현재 행의 이전 행.

    • 현재 행.

    • 현재 행의 다음 행.

  • NTH_VALUE(menu_price_usd, 2) 호출의 2는 창 프레임의 두 번째 행(이 경우 현재 행)을 지정해요.

  • 현재 행이 창 프레임의 맨 첫 번째 행이면 참조할 이전 행이 없으므로 FIRST_VALUE는 그 행에 대해 NULL을 반환해요.

  • 프레임 경계가 파티션의 행을 넘어 확장되는 경우가 있지만, 존재하지 않는 행은 창 함수 계산에 포함되지 않아요. 예를 들어 현재 행이 파티션의 맨 첫 번째 행이고 창 프레임이 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING이면 참조할 이전 행이 없으므로 FIRST_VALUE 함수는 파티션의 첫 번째 행 값을 반환해요.

  • 테이블의 데이터를 고려하면 세 함수의 결과는 결코 일치하지 않아요. 이 함수들은 프레임의 각 행에 대해 첫 번째, 마지막, 또는 n번째 값을 선택하며, 값 선택은 각 파티션에 개별적으로 적용돼요.

SELECT menu_category, menu_item_name, menu_price_usd,
       FIRST_VALUE(menu_price_usd) OVER (PARTITION BY menu_category ORDER BY menu_price_usd
         ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS first_val,
       NTH_VALUE(menu_price_usd, 2) OVER (PARTITION BY menu_category ORDER BY menu_price_usd
         ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS nth_val,
       LAST_VALUE(menu_price_usd) OVER (PARTITION BY menu_category ORDER BY menu_price_usd
         ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS last_val
  FROM menu_items
  WHERE menu_category = 'Dessert'
  ORDER BY menu_price_usd;
+---------------+--------------------+----------------+-----------+---------+----------+
| MENU_CATEGORY | MENU_ITEM_NAME     | MENU_PRICE_USD | FIRST_VAL | NTH_VAL | LAST_VAL |
|---------------+--------------------+----------------+-----------+---------+----------|
| Dessert       | Popsicle           |           3.00 |      3.00 |    4.00 |     4.00 |
| Dessert       | Ice Cream Sandwich |           4.00 |      3.00 |    4.00 |     5.00 |
| Dessert       | Mango Sticky Rice  |           5.00 |      4.00 |    5.00 |     6.00 |
| Dessert       | Sugar Cone         |           6.00 |      6.00 |    6.00 |     7.00 |
| Dessert       | Waffle Cone        |           6.00 |      5.00 |    6.00 |     6.00 |
| Dessert       | Two Scoop Bowl     |           7.00 |      6.00 |    7.00 |     7.00 |
+---------------+--------------------+----------------+-----------+---------+----------+

이 예제는 IGNORE NULLS와 RESPECT NULLS의 차이를 보여줘요. 샘플 데이터에는 비용 값이 NULL인 행이 포함돼 있어요. 기본 RESPECT NULLS 동작에서는 정렬된 파티션의 첫 번째 행이 NULL 값이면 FIRST_VALUE는 NULL을 반환해요. IGNORE NULLS를 사용하면 FIRST_VALUE는 NULL 값을 건너뛰고 첫 번째 NULL이 아닌 값을 반환해요.

SELECT item_name, item_cost, item_price,
       FIRST_VALUE(item_cost) RESPECT NULLS
         OVER (ORDER BY item_price) AS first_cost_respect,
       FIRST_VALUE(item_cost) IGNORE NULLS
         OVER (ORDER BY item_price) AS first_cost_ignore
  FROM VALUES
    ('Pretzel', NULL, 3.00),
    ('Corn Dog', NULL, 4.00),
    ('Hot Dog', 1.50, 5.00),
    ('Sandwich', 2.50, 6.00)
  AS menu(item_name, item_cost, item_price)
  ORDER BY item_price;
+-----------+-----------+------------+--------------------+-------------------+
| ITEM_NAME | ITEM_COST | ITEM_PRICE | FIRST_COST_RESPECT | FIRST_COST_IGNORE |
|-----------+-----------+------------+--------------------+-------------------|
| Pretzel   |      NULL |       3.00 |               NULL |              1.50 |
| Corn Dog  |      NULL |       4.00 |               NULL |              1.50 |
| Hot Dog   |      1.50 |       5.00 |               NULL |              1.50 |
| Sandwich  |      2.50 |       6.00 |               NULL |              1.50 |
+-----------+-----------+------------+--------------------+-------------------+

더 알아보기