表函数

表函数(也称为表值函数 (TVF))是用户定义的函数,表函数会返回表。您可以在可使用表的任何位置使用表函数。表函数的行为与视图类似,但表函数可以接受参数。

创建表函数

要创建表函数,请使用 CREATE TABLE FUNCTION 语句。表函数包含生成表的查询。函数会返回查询结果。以下表函数接受 INT64 参数,并在针对名为 bigquery-public-data.usa_names.usa_1910_current公共数据集的查询中的 WHERE 子句内使用此值:

CREATE OR REPLACE TABLE FUNCTION mydataset.names_by_year(y INT64)
AS (
  SELECT year, name, SUM(number) AS total
  FROM `bigquery-public-data.usa_names.usa_1910_current`
  WHERE year = y
  GROUP BY year, name
);

如需以其他方式进行过滤,您可以将多个参数传递给表函数。以下表函数按年份和名称前缀过滤数据:

CREATE OR REPLACE TABLE FUNCTION mydataset.names_by_year_and_prefix(
  y INT64, z STRING)
AS (
  SELECT year, name, SUM(number) AS total
  FROM `bigquery-public-data.usa_names.usa_1910_current`
  WHERE
    year = y
    AND STARTS_WITH(name, z)
  GROUP BY year, name
);

表参数

您可以将 TVF 参数设置为表。在表参数名称之后,您必须明确指定所需的表架构,方法与指定结构体的字段相同。您传递给 TVF 的表参数可以包含参数架构中指定的列以外的其他列,并且这些列可以按任意顺序显示。

以下表函数会返回一个表,其中包含来自 orders 表的 item_name 的总销售额:

CREATE TABLE FUNCTION mydataset.compute_sales (
  orders TABLE<sales INT64, item STRING>, item_name STRING)
AS (
  SELECT SUM(sales) AS total_sales, item
  FROM orders
  WHERE item = item_name
  GROUP BY item
);

参数名称

如果表函数参数与表列的名称相匹配,则可能会产生有歧义的引用。在这种情况下,BigQuery 会将名称解释为对表列(而不是参数)的引用。建议您使用与任何引用的表列名称不同的参数名称。

使用表函数

您可以在表在其中有效的任何上下文中调用表函数。以下示例在 SELECT 语句的 FROM 子句中调用 mydataset.names_by_year 函数:

SELECT * FROM mydataset.names_by_year(1950)
  ORDER BY total DESC
  LIMIT 5

结果如下所示:

+------+--------+-------+
| year |  name  | total |
+------+--------+-------+
| 1950 | James  | 86447 |
| 1950 | Robert | 83717 |
| 1950 | Linda  | 80498 |
| 1950 | John   | 79561 |
| 1950 | Mary   | 65546 |
+------+--------+-------+

您可以将一个表函数的输出与另一个表联接:

SELECT *
  FROM `bigquery-public-data.samples.shakespeare` AS s
  JOIN mydataset.names_by_year(1950) AS n
  ON n.name = s.word

您还可以在子查询中使用表函数:

SELECT ARRAY(
  SELECT name FROM mydataset.names_by_year(1950)
  ORDER BY total DESC
  LIMIT 5)

调用具有表参数的表函数时,您必须在表参数名称前使用 TABLE 关键字。表参数可以包含表参数架构中未列出的列:

CREATE TABLE FUNCTION mydataset.compute_sales (
  orders TABLE<sales INT64, item STRING>, item_name STRING)
AS (
  SELECT SUM(sales) AS total_sales, item
  FROM orders
  WHERE item = item_name
  GROUP BY item
);

WITH my_orders AS (
    SELECT 1 AS sales, "apple" AS item, 0.99 AS price
    UNION ALL
    SELECT 2, "banana", 0.49
    UNION ALL
    SELECT 5, "apple", 0.99)
SELECT *
FROM mydataset.compute_sales(TABLE my_orders, "apple");

/*-------------+-------+
 | total_sales | item  |
 +-------------+-------+
 | 6           | apple |
 +-------------+-------*/

列出表函数

表函数是一种例程。如需列出数据集中的所有例程,请参阅列出例程

删除表函数

如需删除表函数,请使用 DROP TABLE FUNCTION 语句:

DROP TABLE FUNCTION mydataset.names_by_year

向例程授权

您可以将表函数授权为例程。借助授权例程,您可以与特定用户或群组共享查询结果,而无需为其授予生成结果的底层表的访问权限。例如,已获授权的例程可以计算对数据的聚合,也可以查找表值并在计算中使用该值。如需了解详情,请参阅已获授权的例程

限制

  • 查询正文必须是 SELECT 语句,并且不能修改任何内容。例如,表函数中不允许使用数据定义语言 (DDL) 和数据操纵语言 (DML) 语句。如果您需要副作用,请考虑改为编写过程

  • 表函数必须与其引用的表存储在同一位置。

配额

如需详细了解表函数配额和限制,请参阅配额和限制