SparkSQL—sequence 函数用法详解
SparkSQL— sequence 函数用法详解
sequence
是 Apache Spark SQL 中的一个内置函数,从 Spark 2.4.0 版本开始支持。
用于生成一个等差序列数组,可以是数值型(如整数、长整型)或时间类型(如日期、时间戳)的序列。
官网:https://spark.apache.org/docs/latest/api/sql/index.html#sequence
sequence(start, stop, step)
start
: 起始值(包含)stop
: 结束值(包含)step
: 步长(可选),默认为1
或-1
,取决于start
和stop
的大小关系
⚠️ tips:
stop
是包含的(inclusive),这与很多编程语言中的 range 不同。
支持的数据类型:
类型 | 示例 |
---|---|
byte , short , integer , long | sequence(1, 5) → [1,2,3,4,5] |
date | sequence(date'2023-01-01', date'2023-01-05') |
timestamp | sequence(timestamp'2023-01-01 00:00:00', ..., interval 1 hour) |
参数规则:
规则 | 说明 |
---|---|
start 和 stop 必须同类型 | 不能混合类型,如 int 和 long 可以隐式转换,但 date 和 timestamp 不行 |
step 类型要求 | |
- 数值类型:step 必须是 byte/short/int/long | sequence(1, 10, 2) |
- 时间类型(date /timestamp ):step 必须是 interval 类型 | interval 1 month , interval '2' day |
步长方向 | |
- 若 start <= stop ,step 必须 ≥ 0(默认为 1) | |
- 若 start > stop ,step 必须 < 0(默认为 -1) | |
时间类型的默认步长 | |
- date : 1 day 或 -1 day | |
- timestamp : 1 second 或 -1 second |
Demo:
1. 数值序列(整数)
SELECT sequence(1, 5);
-- 结果: [1, 2, 3, 4, 5]SELECT sequence(5, 1);
-- 结果: [5, 4, 3, 2, 1]
SELECT sequence(0, 10, 2);
-- 结果: [0, 2, 4, 6, 8, 10]
2. 日期序列
SELECT sequence(to_date('2023-01-01'), to_date('2023-01-05')
);
-- 结果: ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05']SELECT sequence(to_date('2023-01-01'), to_date('2023-03-01'), interval 1 month
);
-- 结果: ['2023-01-01', '2023-02-01', '2023-03-01']
3. 时间戳序列
SELECT sequence(timestamp'2023-01-01 00:00:00', timestamp'2023-01-01 03:00:00', interval 1 hour
);
-- 结果: ['2023-01-01 00:00:00', '2023-01-01 01:00:00', '2023-01-01 02:00:00', '2023-01-01 03:00:00']
4. 年月间隔(Year-Month Interval)
SELECT sequence(to_date('2023-01-01'), to_date('2023-12-01'), interval '0-1' year to month
);
-- 每月1号,共12个月
'0-1' year to month
部分 | 含义 |
---|---|
0 | 表示 0 年 |
1 | 表示 1 个月 |
year to month | 表示这个间隔精确到“年-月”级别(不包括天、小时等) |
'0-1' year to month
= 增加 1 个月
等价写法:
interval 1 month
假设你有一张销售表,只有某些月份有数据:
month | sales |
---|---|
2023-01-01 | 100 |
2023-03-01 | 150 |
2023-06-01 | 200 |
补全所有月份(没有数据的设为 0)——先用 sequence
生成完整月份列表,然后 LEFT JOIN
:
WITH all_months AS (SELECT explode(sequence(to_date('2023-01-01'), to_date('2023-12-01'), interval 1 month)) AS month
)
SELECT am.month,COALESCE(s.sales, 0) AS sales
FROM all_months am
LEFT JOIN sales_table s ON am.month = s.month
ORDER BY am.month;
5. 负步长(递减序列)
SELECT sequence(10, 5, -1);
-- [10, 9, 8, 7, 6, 5]SELECT sequence(to_date('2023-03-01'), to_date('2023-01-01'), interval -1 month);
-- ['2023-03-01', '2023-02-01', '2023-01-01']
常见错误用法:
| start < stop
但 step < 0
| | start > stop
但 step > 0
|
| 类型不匹配 | 类型错误 | | 时间序列使用非 interval 步长 |
tips:配合explode函数 还是很好用的~
最后来道面试题:
将格式为 ‘1-5,16,11-13,9’ 的字符串展开为单独的数字,并保留原始位置信息。
预期结果:‘1,2,3,4,5,16,11,12,13,9’
整体代码: