SQL窗口函数总结

本文详细介绍了SQL窗口函数的概念、关键术语、语法以及常用的聚合、排名和分析窗口函数,如LAG、LEAD、FIRST_VALUE、LAST_VALUE和NTILE。通过实例展示了如何在实际场景中运用这些函数进行数据分析。
摘要由CSDN通过智能技术生成

Window Functions

SQL的窗口函数是一种非常强大的工具,用于进行复杂的数据分析和计算,而不需要将数据分组到多个输出行中。你可以在单个查询中完成排序、排名、累积等多种计算。窗口函数也称为OLAP(在线分析处理)函数。

基本概念

窗口函数在执行普通的SQL查询后对结果集进行操作。这意味着先执行FROM, JOIN, WHERE, GROUP BY, HAVING等语句,然后再应用窗口函数。窗口函数通过定义"窗口"(数据的子集),对这些子集执行计算。

关键术语

  • 窗口:窗口是指定行的集合,这些行是与当前行在某种计算关系上相关联的。
  • OVER():这是窗口函数的核心部分,用于定义窗口的分组方式、排序顺序和窗口的范围。

窗口函数语法

窗口函数的语法如下:

<window_function> OVER (
    PARTITION BY <column1>, <column2>, ...
    ORDER BY <column>
    [ROWS|RANGE BETWEEN <start> AND <end>]
)
  • OVER(ORDER BY date) 指定窗口的排序方式
  • OVER(ROWS BETWEEN <start> AND <END>)
    其中<start><end>可以是以下几种类型:
    • UNBOUNDED PRECEDING: 表示从分区的起始行开始。
    • x PRECEDING: 表示从当前行向前x行(不包括当前行本身),x必须是非负整数。
    • CURRENT ROW: 表示当前行。
    • x FOLLOWING: 表示从当前行向后x行(不包括当前行本身),x必须是非负整数。
    • UNBOUNDED FOLLOWING: 表示直到分区的结束行。
  • OVER(PARTITION BY code) 指定窗口的的分组方式,每个窗口是相互独立的

常用的窗口函数

  1. 聚合窗口函数
  • SUM() OVER()
  • AVG() OVER()
  • MIN() OVER()
  • MAX() OVER()
    这些函数可以在窗口内部对数据进行聚合计算。
  1. 排名窗口函数
  • ROW_NUMBER() OVER()
  • RANK() OVER()
  • DENSE_RANK() OVER()
  • NTILE(n) OVER()
    这些函数用于为数据集中的行分配一个唯一的排名。
  1. 分析窗口函数
  • LEAD(value, offset, default) OVER()
  • LAG(value, offset, default) OVER()
  • FIRST_VALUE() OVER()
  • LAST_VALUE() OVER()
    这些函数可以访问由窗口定义的行集中的前后行。

Example

-- 计算销量环比增幅
SELECT amount / lag(amount) OVER (ORDER BY time) FROM sales;

-- 计算每一行的销量占所属地区的销量百分比
SELECT amount / sum(amount) OVER (PARTITION BY region) FROM sales;

-- 计算差分
SELECT amount - lag(amount) OVER (ORDER BY time) FROM sales;

LAG函数

在 SQL 中,LAG函数是一种窗口函数,它用于访问结果集中当前行的前面的行中的数据。它常常用于分析数据中的时间序列或其他按照某种顺序排列的数据。LAG函数允许你在查询结果中回看若干行,并从中提取信息,非常适合用来进行数据比较或计算数据变化。

语法

LAG函数的基本语法如下:

LAG(expression, offset, default) OVER (partition_order_by_clause)
  • expression: 这是你希望从前面的行中获取的字段或计算表达式。
  • offset: 这是一个可选参数,用于指定你想要回看多少行。默认值是 1,表示回看前一行。
  • default: 这也是一个可选参数,用来定义当没有足够的行可供回看时的返回值(即当前行之前的行数少于指定的 offset)。如果未指定,当没有可回看的行时,默认返回 NULL
  • partition_order_by_clause: 这定义了 LAG 函数操作的数据窗口。它通常包含 ORDER BY 子句来指定数据的排序方式,也可以包含 PARTITION BY 子句来分组数据。

示例

当输入如下查询语句,查询股票数据的差分

SELECT 
    date,
    InnerCode,
    close,
    close - LAG(close, 1, NULL) OVER (PARTITION BY InnerCode ORDER BY date) AS close_change
FROM 
    stk_day
WHERE
    date >= '2019-01-01' AND date <= '2019-01-07'

返回结果如下:

dateInnerCodecloseclose_change
2019-01-02 00:00:00857.16nan
2019-01-03 00:00:00857-0.16
2019-01-04 00:00:00857.120.12
2019-01-07 00:00:00857.150.03
2019-01-02 00:00:0039.19nan
2019-01-03 00:00:0039.280.09
2019-01-04 00:00:0039.750.47
2019-01-07 00:00:0039.74-0.01

LEAD函数

在 SQL 中,LEAD 函数是与 LAG 函数相对的另一种窗口函数,它用于访问结果集中当前行的后面的行中的数据。这种函数非常适用于需要提前查看数据或对数据进行前瞻性分析的情况。

语法

LEAD 函数的基本语法如下:

LEAD(expression, offset, default) OVER (partition_order_by_clause)
  • expression: 这是你希望从后面的行中获取的字段或计算表达式。
  • offset: 这是一个可选参数,用于指定你想要向前查看多少行。默认值是 1,表示查看后一行。
  • default: 这也是一个可选参数,用来定义当没有足够的行可供向前查看时的返回值(即当前行之后的行数少于指定的 offset)。如果未指定,当没有可向前查看的行时,默认返回 NULL。
  • partition_order_by_clause: 这定义了 LEAD 函数操作的数据窗口。它通常包含 ORDER BY 子句来指定数据的排序方式,也可以包含 PARTITION BY 子句来分组数据。

适用场景

LEAD 函数的使用场景包括但不限于:

预测分析,比如预测未来销售额或股票价格变动。
计算时间序列数据的变化,比如温度、汇率、网站访问量的未来趋势。
进行时间偏移的数据对比,例如在电影评分中比较观众对连续电影的评价差异。
通过使用 LEADLAG,可以实现复杂的数据分析任务,包括时间序列数据的前后比较,以及基于过去或未来数据点的预测和分析。这两个函数在数据处理和分析领域中都非常重要,它们增强了 SQL 查询的能力,使之能够解决更多高级的问题。

示例

如果希望计算某些股票未来一天的简单收益率,可以通过如下语句计算查询

SELECT 
    date,
    InnerCode,
    close,
    (LEAD(close, 1, NULL) OVER (PARTITION BY InnerCode ORDER BY date) - close) / close AS return_rate
FROM 
    stk_day
WHERE
    date >= '2019-01-01' AND date <= '2019-01-07'
dateInnerCodeclosereturn_rate
2019-01-02 00:00:00857.16-0.0223464
2019-01-03 00:00:008570.0171429
2019-01-04 00:00:00857.120.00421348
2019-01-07 00:00:00857.15nan
2019-01-02 00:00:0039.190.00979325
2019-01-03 00:00:0039.280.0506466
2019-01-04 00:00:0039.75-0.00102564
2019-01-07 00:00:0039.74nan

在这个查询中:

  • LEAD(close, 1, NULL) OVER (PARTITION BY InnerCode ORDER BY date)计算得到每个股票一天后的收盘价,其中PARTITION BY InnerCode通过股票代码来区分不同股票,用ORDER BY date指定了窗口函数的排序方式
  • 如果最后一行没有后一行,LEAD 函数将返回 NULL,从而使 return_rateNULL

FIRST_VALUE函数

FIRST_VALUE 是一个窗口函数,它从定义的窗口中返回第一个值,基于指定的排序顺序。这个函数非常有用,尤其是在需要从每个分组中提取最初记录的情景中。

示例

通过 FIRST_VALUE 函数查询分组中的第一个值

SELECT 
    date,
    InnerCode,
    close,
    FIRST_VALUE(close) OVER (PARTITION BY InnerCode ORDER BY date) AS first_row
FROM 
    stk_day
WHERE
    date >= '2019-01-01' AND date <= '2019-01-07'

返回结果如下:

dateInnerCodeclosefirst_row
2019-01-02 00:00:00857.167.16
2019-01-03 00:00:008577.16
2019-01-04 00:00:00857.127.16
2019-01-07 00:00:00857.157.16
2019-01-02 00:00:0039.199.19
2019-01-03 00:00:0039.289.19
2019-01-04 00:00:0039.759.19
2019-01-07 00:00:0039.749.19

LAST_VALUE函数

LAST_VALUE函数与FIRST_VALUE函数用法大致相同,不同的是,其获取的是窗口中的最后一个值

NTILE函数

NTILE() 是 SQL 中的一种窗口函数,用于将有序分区中的行分成指定数量的近似等大小的组,并为每一行分配一个组号。这种分组是基于排序顺序来确定的。NTILE() 函数非常有用于执行分位数分析、数据分段、以及在统计分析中均匀切分数据集。

语法

NTILE() 函数的基本语法如下:

NTILE(number_of_tiles) OVER (
    [PARTITION BY partition_expression, ...]
    ORDER BY sort_expression [ASC|DESC], ...
)
  • number_of_tiles:一个正整数,定义要将数据分割成多少个组。
  • PARTITION BY:可选,按指定列的值对结果集进行分组。如果省略,整个结果集被视为一个单一的分区。
  • ORDER BY:定义如何对数据进行排序,排序的基础是分组的依据

工作原理

NTILE() 函数首先根据 ORDER BY 子句对数据进行排序。然后,根据 number_of_tiles 参数将这些排序后的数据分割成指定数量的组。如果数据总数不能被组数整除,那么前几个组将包含一个额外的数据行。

示例

使用 NTILE() 函数将股票的收盘价分为高和低两部分

SELECT 
    date,
    InnerCode,
    close,
    NTILE(2) OVER (PARTITION BY InnerCode ORDER BY close ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) AS cluster
FROM 
    stk_day
WHERE
    date >= '2019-01-01' AND date <= '2019-01-15'
ORDER BY
    InnerCode,date

返回结果如下:

dateInnerCodeclosecluster
2019-01-02 00:00:00857.161
2019-01-03 00:00:008571
2019-01-04 00:00:00857.121
2019-01-07 00:00:00857.151
2019-01-08 00:00:00857.22
2019-01-09 00:00:00857.22
2019-01-10 00:00:00857.242
2019-01-11 00:00:00857.272
2019-01-14 00:00:00857.141
2019-01-15 00:00:00857.182
  • 35
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spark SQL窗口函数是一种用于对数据进行分组和排序的函数。它可以在查询结果中创建一个窗口,然后在窗口内进行聚合、排序和分析操作。窗口函数的语法结构如下所示: <窗口函数>(参数) OVER ( [PARTITION BY <列清单>] [ORDER BY <排序用清单列>] [ASC/DESC] (ROWS | RANGE) <范围条件> ) 其中,关键字OVER表示这是一个窗口函数,不是普通的聚合函数。PARTITION BY子句用于指定分组字段,ORDER BY子句用于指定排序字段。ROWS/RANGE窗口子句用于控制窗口的尺寸边界,有两种选项:ROW表示物理窗口,数据筛选基于排序后的索引;RANGE表示逻辑窗口,数据筛选基于值。[1] 在Spark SQL中,窗口函数可以通过使用Column提供的over函数来实现。下面是一个示例代码,展示了如何使用窗口函数进行累加历史和全部统计: ```scala import org.apache.spark.sql.expressions._ val first_2_now_window = Window.partitionBy("pcode").orderBy("event_date") df_userlogs_date.select( $"pcode", $"event_date", sum($"duration").over(first_2_now_window).as("sum_duration") ).show ``` 以上代码使用了窗口函数sum来计算每个pcode和event_date的duration的累加值,并将结果命名为sum_duration。通过使用over函数和指定的窗口(first_2_now_window),我们可以在每个窗口内进行累加计算。最后,使用show方法展示结果。[3] 总结来说,Spark SQL窗口函数是一种强大的工具,可以在查询结果中创建窗口,并在窗口内进行聚合、排序和分析操作。它可以通过使用Column提供的over函数来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值