- 类别:
:doc:`/sql-reference/functions-window-syntax`(排名)
FIRST_VALUE¶
返回一组有序值中的第一个值。
- 另请参阅:
语法¶
FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ]
OVER ( [ PARTITION BY <expr1> ] ORDER BY <expr2> [ { ASC | DESC } ] [ NULLS { FIRST | LAST } ] [ <window_frame> ] )
有关 window_frame 语法的详细信息,请参阅 窗口函数的语法和用法。
实参¶
expr确定返回值的表达式。
expr1用于对行进行分区的表达式。您可以指定单个表达式或以逗号分隔的表达式列表。例如:
PARTITION BY column_1, column_2
expr2用于对行进行排序的表达式。您可以指定单个表达式或以逗号分隔的表达式列表。例如:
ORDER BY column_3, column_4
{ IGNORE | RESPECT } NULLS当
expr包含 NULL 值时,是忽略还是遵照 NULL 值:IGNORE NULLS返回第一个非 NULL 值。如果
RESPECT NULLS是表达式中的第一个值,则返回一个 NULL 值。
默认值:
RESPECT NULLS
使用说明¶
此函数是与排名相关的函数,因此它必须指定一个窗口。窗口子句由以下分子句组成:
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 语法的详细信息,请参阅 窗口函数的语法和用法。
示例¶
This example shows a query that uses the FIRST_VALUE function to find the cheapest menu item in each category. The query contains two ORDER BY clauses: one to control the order of rows in each partition, and one to sort the output of the full query. To create and load the table that is used in this example, see 创建并加载 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 |
+---------------+--------------------+----------------+---------------+
The following example also uses the menu_items table to compare three related functions: FIRST_VALUE,
NTH_VALUE, and LAST_VALUE:
该查询创建一个三行宽的滑动窗口框架,其中包含:
当前行前面的行。
当前行。
当前行后面的行。
The
2in the callNTH_VALUE(menu_price_usd, 2)specifies the second row in the window frame (which, in this case, is also the current row).当前行是窗口框架中的第一行时,没有前面的行可以引用,因此 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 |
+-----------+-----------+------------+--------------------+-------------------+