TLDR:您想要的查询是:
SELECT
x,
LAST_VALUE(y) OVER (PARTITION BY x ORDER BY y ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM table
可能后跟GROUP BY 以折叠来自分析函数的重复输出行。
当然,如果您只需要在无序分区上使用 MAX 会更简单:
SELECT
x,
MAX(y) OVER (PARTITION BY x)
FROM table
在回答这个问题之前,这里先介绍一下分析函数(又名窗口函数)的背景知识。以下所有内容都是标准 SQL,并非特定于 BigQuery。
首先,分析函数不是聚合函数。聚合函数将多个输入行折叠成单个输出行,而分析函数为每个输入行精确计算一个输出行。因此,您需要确保您正在考虑 每个 输入行的输出。
其次,分析函数在行“窗口”上运行,该行“窗口”是行所属“分区”的子集。输入行的分区由PARTITION BY 子句确定,或者如果您希望分区是整个输入行集,则可以省略它。窗口由ROWS 子句给出,但如果您不指定它(用户通常不指定),它默认为整个分区(未应用排序时)或分区中的行集从第一行到当前行(当存在ORDER BY 时)。请注意,分区中每个输入行的窗口可能不同!
现在,回到LAST_VALUE。尽管上面描述的默认窗口在许多情况下是合理的(例如,计算累积和),但它在 LAST_VALUE 上的效果非常糟糕。 LAST_VALUE函数返回窗口最后一行的值,默认窗口最后一行就是当前行。
因此,要解决此问题,您需要明确指定 LAST_VALUE 的窗口是整个分区,而不仅仅是当前行之前的行。你可以这样做:
SELECT x, LAST_VALUE(y) OVER (PARTITION BY x ORDER BY y ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM table
为了测试这一点,这里有一个例子:
SELECT
x,
FIRST_VALUE(x) OVER (ORDER BY x ASC) first_asc,
FIRST_VALUE(x) OVER (ORDER BY x DESC) first_desc,
LAST_VALUE(x) OVER (ORDER BY x ASC) last_asc,
LAST_VALUE(x) OVER (ORDER BY x DESC) last_desc,
FROM
(SELECT 4 as x),
(SELECT 2 as x),
(SELECT 1 as x),
(SELECT 3 as x)
x,first_asc,first_desc,last_asc,last_desc
1,1,4,1,1
2,1,4,2,2
3,1,4,3,3
4,1,4,4,4
请注意,LAST_VALUE 返回 1、2、3、4 而不仅仅是 4,因为每个输入行的窗口都会发生变化。
现在让我们指定一个作为整个分区的窗口:
SELECT
x,
FIRST_VALUE(x) OVER (ORDER BY x ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_asc,
FIRST_VALUE(x) OVER (ORDER BY x DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_desc,
LAST_VALUE(x) OVER (ORDER BY x ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) last_asc,
LAST_VALUE(x) OVER (ORDER BY x DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) last_desc,
FROM
(SELECT 4 as x),
(SELECT 2 as x),
(SELECT 1 as x),
(SELECT 3 as x)
x,first_asc,first_desc,last_asc,last_desc
1,1,4,4,1
2,1,4,4,1
3,1,4,4,1
4,1,4,4,1
现在我们得到 4 个 LAST_VALUE 符合预期。