窗口函数

窗口函数对查询结果中的行执行计算。窗口函数在HAVING子句之后、ORDER BY子句之前运行。调用窗口函数需要使用特殊的语法(使用OVER子句来指定窗口)。一个窗口由三部分组成:

  • 分区规范,它将输入行划分到不同的分区中。这与GROUP BY子句将行划分到不同的组中以用于聚合函数的方式类似。
  • 排序规范,它确定窗口函数处理输入行的顺序。
  • 窗口框架,它为给定的行指定要由函数处理的行滑动窗口。如果未指定框架,则默认使用RANGE UNBOUNDED PRECEDING,它与RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同。该框架包含从分区开头开始到当前行的最后一个对等点的所有行。

例如,以下查询按价格对每个售货员的订单进行排序:

  1. SELECT orderkey, clerk, totalprice,
  2. rank() OVER (PARTITION BY clerk
  3. ORDER BY totalprice DESC) AS rnk
  4. FROM orders
  5. ORDER BY clerk, rnk

聚合函数

通过添加OVER子句,可以将所有aggregate用作窗口函数。会为当前行的窗口框架中的每个行计算聚合函数。

例如,以下查询为每个售货员生成按天滚动的订单价格总和:

  1. SELECT clerk, orderdate, orderkey, totalprice,
  2. sum(totalprice) OVER (PARTITION BY clerk
  3. ORDER BY orderdate) AS rolling_sum
  4. FROM orders
  5. ORDER BY clerk, orderdate, orderkey

排序函数

cume_dist() -> bigint

返回一组值中某个值的累积分布。结果是窗口分区的窗口排序中的行前面或与之对等的行数量除以窗口分区中的总行数。因此,排序中的任何绑定值都将计算为相同的分布值。

dense_rank() -> bigint

返回某个值在一组值中的排序。这与rank类似,只是绑定值不在序列中产生间隙。

ntile(n) -> bigint

将每个窗口分区的行分到n个桶中,范围为1n(最大)。桶值最多相差1。如果分区中的行数未平均分成桶数,则从第一个桶开始每个桶分配一个剩余值。

例如,对于6行和4个桶,桶值如下:1 1 2 2 3 4

percent_rank() -> double

返回某个值在一组值中的百分比排名。结果是(r - 1) / (n - 1),其中r是该行的rankn是窗口分区中的总行数。

rank() -> bigint

返回某个值在一组值中的排序。排序是该行之前与该行不对等的行数加一。

因此,排序中的绑定值将在序列中产生间隙。会对每个窗口分区进行排序。

row_number() -> bigint

根据窗口分区内行的排序,从1开始返回每行的唯一序列号。

值函数

first_value(x) -> [与输入相同]

返回窗口的第一个值。

last_value(x) -> [与输入相同]

返回窗口的最后一个值。

nth_value(x, offset) -> [与输入相同]

返回相对于窗口开头的指定偏移处的值。偏移从1开始。偏移可以是任何标量表达式。如果偏移为NULL或大于窗口中的值的数量,则返回NULL。如果偏移为零或负数,则产生错误。

lead(x[, offset [, default_value]]) -> [与输入相同]

返回窗口中当前行之后offset行处的值。偏移从0(当前行)开始。偏移可以是任何标量表达式。默认offset1。如果偏移为NULL或大于窗口,则返回default_value,如果未指定该值,则返回null

lag(x[, offset [, default_value]]) -> [与输入相同]

返回窗口中当前行之前offset行处的值。偏移从0(当前行)开始。偏移可以是任何标量表达式。默认offset1。如果偏移为NULL或大于窗口,则返回default_value,如果未指定该值,则返回null