重新使用 BigQuery window 函数分区
Re-use BigQuery window function partition
我需要 select 多个列作为 LEAD 语句的一部分。这 看起来 效率真的很低,所需的排序和分区数量增加了三倍 ->
SELECT
field,
field2,
field3,
LEAD(field, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField,
LEAD(field2, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField2,
LEAD(field3, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField3,
FROM dataset.table
- 有更好的方法吗?
- BigQuery 是否会在查询运行时对此进行优化以提高效率?
Window Functions 已经足够优雅,可以在 SQL 中表达您的业务逻辑。尽管看起来您需要为 SELECT 语句的每个相应输出字段重复 PARTITION BY ... ORDER BY ...
部分,但我个人认为这不是 window 函数给我们的强大功能的巨大代价。
顺便说一句,您不限于对所有输出字段使用相同的 PARTITION BY
- 您可以为每个字段使用您需要的任何分区。 ORDER BY
相同
Does BigQuery optimize for this at query runtime to make it efficient?
您可以在 运行 查询后检查 Query Plan Explanation。
它清楚地表明,无论您使用多少 Window 函数,BigQuery 都会重复使用分区。看起来如果你有几个不同的分区,它们就会被级联。 (如果你看到查询计划,这也很清楚)
Is there a better way to do this?
您可以通过多种方式模仿 window 分区功能。 None 他们似乎执行 and/or readable/manageable 和使用 window 功能一样好
例如,下面的逻辑将产生相同的结果(这里只是高级逻辑)。
您将 ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ...) as POS
应用于原始 data/table。
比你用 ON a.partition=b.partition AND a.POS = a.(POS + 1) <-- 这只是逻辑,而不是实现
所以现在,您将在 table 中拥有别名 a 的所有当前值和 table 别名 b
中的所有下一个值
正如我所提到的,上面产生的结果与 window 函数完全相同,但代码看起来更丑陋并且执行显示更昂贵
要添加到 Mikhail 的回答中的几点:
是的,BigQuery 对其进行了优化 - 如果 window 框架相同,它将只设置一次,并且多个函数将 运行 覆盖它。
你是对的,一遍又一遍地编写相同的框架很乏味,因此我们致力于改进 BigQuery SQL 方言,使其更符合标准,并在不久的将来* 你将能够写
SELECT
field,
field2,
field3,
LEAD(field, 1) OVER w1 AS nextField,
LEAD(field2, 1) OVER w1 AS nextField2,
LEAD(field3, 1) OVER w1 AS nextField3,
FROM dataset.table
WINDOW w1 AS (PARTITION BY field ORDER BY field ASC)
*不能给你确切的日期,但目前正在内部测试中,所以应该不会太长。
我需要 select 多个列作为 LEAD 语句的一部分。这 看起来 效率真的很低,所需的排序和分区数量增加了三倍 ->
SELECT
field,
field2,
field3,
LEAD(field, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField,
LEAD(field2, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField2,
LEAD(field3, 1) OVER (PARTITION BY field ORDER BY field ASC) AS nextField3,
FROM dataset.table
- 有更好的方法吗?
- BigQuery 是否会在查询运行时对此进行优化以提高效率?
Window Functions 已经足够优雅,可以在 SQL 中表达您的业务逻辑。尽管看起来您需要为 SELECT 语句的每个相应输出字段重复 PARTITION BY ... ORDER BY ...
部分,但我个人认为这不是 window 函数给我们的强大功能的巨大代价。
顺便说一句,您不限于对所有输出字段使用相同的 PARTITION BY
- 您可以为每个字段使用您需要的任何分区。 ORDER BY
Does BigQuery optimize for this at query runtime to make it efficient?
您可以在 运行 查询后检查 Query Plan Explanation。
它清楚地表明,无论您使用多少 Window 函数,BigQuery 都会重复使用分区。看起来如果你有几个不同的分区,它们就会被级联。 (如果你看到查询计划,这也很清楚)
Is there a better way to do this?
您可以通过多种方式模仿 window 分区功能。 None 他们似乎执行 and/or readable/manageable 和使用 window 功能一样好
例如,下面的逻辑将产生相同的结果(这里只是高级逻辑)。
您将 ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ...) as POS
应用于原始 data/table。
比你用 ON a.partition=b.partition AND a.POS = a.(POS + 1) <-- 这只是逻辑,而不是实现
所以现在,您将在 table 中拥有别名 a 的所有当前值和 table 别名 b
正如我所提到的,上面产生的结果与 window 函数完全相同,但代码看起来更丑陋并且执行显示更昂贵
要添加到 Mikhail 的回答中的几点:
是的,BigQuery 对其进行了优化 - 如果 window 框架相同,它将只设置一次,并且多个函数将 运行 覆盖它。
你是对的,一遍又一遍地编写相同的框架很乏味,因此我们致力于改进 BigQuery SQL 方言,使其更符合标准,并在不久的将来* 你将能够写
SELECT
field,
field2,
field3,
LEAD(field, 1) OVER w1 AS nextField,
LEAD(field2, 1) OVER w1 AS nextField2,
LEAD(field3, 1) OVER w1 AS nextField3,
FROM dataset.table
WINDOW w1 AS (PARTITION BY field ORDER BY field ASC)
*不能给你确切的日期,但目前正在内部测试中,所以应该不会太长。