我想y使用如下查询找到有序分区的最后一个值:
SELECT
x,
LAST_VALUE(y) OVER (PARTITION BY x ORDER BY y ASC)
FROM table
Run Code Online (Sandbox Code Playgroud)
但是LAST_VALUE返回许多值,这些值不是y给定分区的最后一个值(在这种情况下,最大值).为什么?
(在这种情况下,MAX可以用来代替LAST_VALUE找到最大值,但为什么不LAST_VALUE返回最大值?)
Jer*_*dit 24
TLDR:您想要的查询是:
SELECT
x,
LAST_VALUE(y) OVER (PARTITION BY x ORDER BY y ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM table
Run Code Online (Sandbox Code Playgroud)
可能接着GROUP BY从分析函数中折叠重复的输出行.
当然,只要MAX你需要它就可以更简单地使用无序分区:
SELECT
x,
MAX(y) OVER (PARTITION BY x)
FROM table
Run Code Online (Sandbox Code Playgroud)
在回答这个问题之前,这里有一些关于分析函数(也就是窗口函数)的背景知识.以下所有内容都是标准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
Run Code Online (Sandbox Code Playgroud)
为了测试这个,这是一个例子:
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
Run Code Online (Sandbox Code Playgroud)
请注意,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
Run Code Online (Sandbox Code Playgroud)
现在我们LAST_VALUE按预期得到4分.