FIRST_VALUE
FIRST_VALUE
FIRST_VALUE()는 정렬된 값 그룹 내에서 첫 번째 값을 반환해요.
함께 보기:
LAST_VALUE , NTH_VALUE
본문
문법
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 |
+-----------+-----------+------------+--------------------+-------------------+