前言:
💞💞大家好,我是书生♡,本阶段和大家一起分享和探索大数据技术Spark—SparkSQL,本篇文章主要讲述了:Spark SQL高级技巧:SQL语句、缓存/Checkpoint、高效Join、数据清洗及内置函数的应用等等。欢迎大家一起探索讨论!!!
💞💞代码是你的画笔,创新是你的画布,用它们绘出属于你的精彩世界,不断挑战,无限可能!
个人主页⭐: 书生♡
gitee主页🙋♂:闲客
专栏主页💞:大数据开发
博客领域💥:大数据开发,java编程,前端,算法,Python
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬
目录
1. DataFrame的SQL语句方式
当使用 PySpark 处理数据时,DataFrame API 提供了一种声明式的编程模型,它非常接近 SQL 语言。使用 DataFrame API,您可以使用 SQL 语句来查询和操作数据,这使得数据处理更加直观和易于理解。
主要有两个步骤:
- 将df映射成一张表
df.createTempView(name=表名)
- 执行sql语句
sparksession.sql(sqlQuery=sql语句)
- 第一步:创建一个DF对象
通过读取文件获得RDD类型的数据,在通过RDD的算子进行转换数据,得到一个二维的RDD对象,最后通过RDD.ToDF方法转化为DF
# 使用DF的DSL方法实现对df数据处理
# DF的数据是结构化数据,所以DSL方法和SQL的关键字基本一致
from pyspark.sql import SparkSession
# 创建SparkSession对象
ss = SparkSession.builder.getOrCreate()
# 使用sparkcontext读取hdfs上的文件数据
sc = ss.sparkContext
# 将读取的文件数据转化为rdd
rdd = sc.textFile('hdfs://node1:8020/data/stu.txt')
res1 = rdd.collect()
# print(f'rdd文件数据:{res1}')
# 将每行字符串数据切割转为二维rdd
rdd_split = rdd.map(lambda x: x.split(','))
res2 = rdd_split.collect()
# print(f'切割后的rdd数据:{res2}')
# 将rdd转为df数据
df = rdd_split.toDF(
schema='id string,name string,gender string,age string,birthday string,major string,hobby string,create_time string')
# df.show()
- 第二步:将DF对象映射成一个表
通过DF对象的createTempView方法
df.createTempView('student') # 将DF转换为一个表,表名为student
- 第三步:写sql语句,这个跟hivesql 和mysql是一样的
sql_str = 'select cast(id as int),gender,name,cast(age as int) from student'
- 第四步:执行sql语句
通过sparksession的sql方法执行SQL
df_sql = ss.sql(sqlQuery=sql_str)
# 查看数据
df_sql.show()
df_sql.printSchema()
print("******************************************")
df_sql1 = 'select gender,cast(avg(age) as int) as avg_age from student group by gender'
df_Sql2 = ss.sql(sqlQuery=df_sql1)
df_Sql2.show()
2. DSL高级方法
2.1 DSL高级方法 – 缓存和checkpoint
在 PySpark 中,使用 DataFrame API 进行数据处理时,有时需要对数据集进行缓存或设置检查点,以提高多次访问同一数据集时的性能。这两种技术都是为了减少数据重新计算的成本,特别是在需要多次迭代或重复使用同一个 DataFrame 时尤为重要。
- 缓存 (Caching)
缓存是一种将计算结果存储在内存中,以便后续计算可以重用的技术。这在处理大型数据集时非常有用,尤其是在数据需要多次访问的情况下。
- 使用持久化
除了存入缓存方法之外,您还可以使用 checkpoint() 方法,将数据存储到HDFS中,这就不害怕丢失了。
数据准备:创建DF对象
from pyspark import StorageLevel
# 使用DF的DSL方法实现对df数据处理
# DF的数据是结构化数据,所以DSL方法和SQL的关键字基本一致
from pyspark.sql import SparkSession
# 创建SparkSession对象
ss = SparkSession.builder.getOrCreate()
# 使用sparkcontext读取hdfs上的文件数据
sc = ss.sparkContext
# 将读取的文件数据转化为rdd
rdd = sc.textFile('hdfs://node1:8020/data/stu.txt')
res1 = rdd.collect()
# print(f'rdd文件数据:{res1}')
# 将每行字符串数据切割转为二维rdd
rdd_split = rdd.map(lambda x: x.split(','))
res2 = rdd_split.collect()
# print(f'切割后的rdd数据:{res2}')
# 将rdd转为df数据
df = rdd_split.toDF(
schema='id string,name string,gender string,age string,birthday string,major string,hobby string,create_time string')
- 将DF数据进行缓存
缓存的同时,设置两个备份,使用persist
方法,级别为MEMORY_ONLY_2
# 缓存df数据
df.persist(storageLevel=StorageLevel.MEMORY_ONLY_2)
- 查看缓存状态以及释放缓存
# 获取df是否缓存
print(df.is_cached)
# 释放df缓存
### df.unpersist()
- 设置持久化的目录 和 设置checkpoint
# 设置持久化的目录
sc.setCheckpointDir('hdfs://node1:8020/checkpoint')
# 设置df的checkpoint
df.checkpoint()
- 查询数据
df_select = df.select(df.id.cast('int'), 'name', 'gender', df.age.cast('int'), 'birthday', 'major', 'hobby')
df_select.show()
- 查看历史服务器
出现了绿色,缓存成功
HDFS上也成功设置了
2.2 DSL高级方法 – join关联
在 PySpark 中,使用 DataFrame API 进行数据处理时,经常需要将两个或多个 DataFrame 进行连接(join),以合并来自不同数据源的信息。PySpark 提供了多种类型的连接操作,以适应不同的数据处理需求。
- Inner Join:
只返回两个 DataFrame 中匹配的记录。
- Left Outer Join:
返回左 DataFrame 中的所有记录,以及右 DataFrame 中匹配的记录。如果没有匹配的记录,则右 DataFrame 的字段为null。
- Right Outer Join:
返回右 DataFrame 中的所有记录,以及左 DataFrame 中匹配的记录。如果没有匹配的记录,则左 DataFrame 的字段为null。
- Full Outer Join:
返回两个 DataFrame 中的所有记录。如果没有匹配的记录,则相应 DataFrame 的字段为 null。
- Left Semi Join:
返回左 DataFrame 中匹配右 DataFrame 的记录,但只包含左 DataFrame 的字段。
- Left Anti Join:
返回左 DataFrame 中不匹配右 DataFrame 的记录。
- Cross Join:
返回两个 DataFrame 中所有可能的组合。
语法格式:
- 内连接
df1.join(df2, on=关联条件, how='inner')
- 左外连接
df1.join(df2, on=关联条件, how='left')
- 右外连接
df1.join(df2, on=关联条件, how='right')
- 满外连接
df1.join(df2, on=关联条件, how='full')
- 上下连接
union/unionAll
注意:关联字段相同的时候可以只写一个字段,单引号引起来 ‘id’
数据准备:创建两个DF对象
# 多个df的关联操作
from pyspark.sql import SparkSession
from pyspark.sql.types import *
# 生成SparkSession对象
ss = SparkSession.builder.getOrCreate()
# SparkSession中可以通过sparkContext获取sparkContext对象
sc = ss.sparkContext
# 生成rdd
rdd1 = sc.parallelize([
[1, 'zhangsan', 20],
[2, 'lisi', 20],
[3, 'wangwu', 22]
])
rdd2 = sc.parallelize([
[3, 'zhaoliu', 20],
[4, 'xiaoming', 21],
[5, 'itcast', 22]
])
# 定义schema信息
schema_type = StructType(). \
add('id', IntegerType()). \
add('name', StringType()). \
add('age', IntegerType(), False)
# toDF 将二维rdd数据转为dataframe数据
df1 = rdd1.toDF(schema_type)
df2 = rdd2.toDF(schema_type)
# df1.show()
# df2.show()
- 左连接–left
# 左外连接
df1.join(other=df2,on=df1.id==df2.id,how='left').show()
- 右连接–right
# 右外连接,关联字段相同的时候可以只写一个字段,单引号引起来
df1.join(other=df2,on='id',how='right').show()
- 内连接 --inner
# 内连接,默认是内连接
df1.join(other=df2,on='id',how='inner').show()
- 全连接-- full
# 全连接
df1.join(other=df2,on=df1.id==df2.id,how='full').show()
- 交叉连接 --crossJoin
# 交叉连接 -> 笛卡尔积, 不写关联条件
df1.crossJoin(other=df2).show()
- union / unionALL
# union/unionAll
df1.union(df2).show()
df1.toDF('id','new_name','new_age').unionAll(df2).show()
2.3 DSL高级方法 – 数据清洗
在 PySpark 中进行数据清洗是一项重要的任务,它可以帮助您准备干净、一致的数据集以供分析。数据清洗通常涉及多种操作,如删除空值、处理异常值、标准化数据格式等。以下是使用 PySpark DataFrame API 进行数据清洗的一些高级方法和示例。
数据清洗的基本步骤
- 删除空值:删除包含缺失值的行或列。
- 填充空值:用平均值、中位数或其他统计值填充缺失值。
- 异常值检测:识别并处理异常值。
- 数据格式标准化:确保数据的一致性,例如日期和时间格式。
- 数据类型转换:确保数据列具有正确的数据类型。
df.drop(列名1, 列名2, ...)
-> 删除列df.dropDuplicates(subset=)
-> 根据指定的列对行数据进行去重, 不写subset对所有列进行去重df.dropna(how=, subset=)
-> 删除缺失值
how: 默认any, 包含缺失值就删除; all, 所有都为缺失值才删除
subset: 指定列df.fillna(value=, subset=)
-> 填充缺失值 value: 填充的值, 默认填充对应类型列 subset: 指定列df.replace(to_replace=, value=, subset=)
-> 替换操作 to_replace: 需要替换的值 value: 替换后的值 subset: 指定列值替换
数据准备:创建DF对象,实现全连接
# 多个df的关联操作
from pyspark.sql import SparkSession
from pyspark.sql.types import *
# 生成SparkSession对象
ss = SparkSession.builder.getOrCreate()
# SparkSession中可以通过sparkContext获取sparkContext对象
sc = ss.sparkContext
# 生成rdd
rdd1 = sc.parallelize([
[1, 'zhangsan', 20],
[2, 'lisi', 20],
[3, 'wangwu', 22]
])
rdd2 = sc.parallelize([
[3, 'zhaoliu', 20],
[4, 'xiaoming', 21],
[5, 'itcast', 22]
])
# 定义schema信息
schema_type = StructType(). \
add('id', IntegerType()). \
add('name', StringType()). \
add('age', IntegerType(), False)
# toDF 将二维rdd数据转为dataframe数据
df1 = rdd1.toDF(schema_type)
df2 = rdd2.toDF(schema_type)
# 全连接
test_df = df1.join(other=df2, on= df1.id==df2.id, how='full').toDF('id1','name1','age1','id2','name2','age2')
test_df.show()
test1_df = test_df
2.3.1 删除列 – drop
df.drop(列名1, 列名2, ...)
-> 删除列
print("********************** 删除列 ************************")
# 删除列
test_df.drop('id2').show()
2.3.2 去重列 – dropDuplicates
df.dropDuplicates(subset=)
print("********************** 去重列 ************************")
# 一列数据去重
test_df.dropDuplicates(subset=['age1']).show()
# 多列数据去重
test_df.dropDuplicates(subset=['id1','name1']).show()
# 全部去重
test_df.dropDuplicates().show()
2.3.3 删除null值 – dropna
df.dropna(how=, subset=)
删除null值 df.dropna(how=, subset=) -> 删除缺失值
how: 默认any, 包含缺失值就删除; all,所有都为缺失值才删除
subset: 指定列
- 全部删除null
## 全部删除null,这一行只要有null,就删除这行
test_df.dropna().show()
test_df.dropna(how='any').show()
- 删除指定列中包含null值对应行
test_df.dropna(subset=['id1']).show()
- how: any默认->任意null值 all->所有值为null值才删除, 一般和subset一起使用
# how: any默认->任意null值 all->所有值为null值才删除, 一般和subset一起使用
test_df.show()
test_df.dropna(how='all',subset=['id1','name1']).show()
2.3.4 填充null值 – fillna
df.fillna(value=, subset=)
df.fillna(value=)
value: 填充的值, 默认填充对应类型列 ,填充的数据是一个整形数据,那么就给整形的数据填充
- 给整数类型的字段填充
test_df.fillna(value=9999).show()
- 给字符串类型的字段填充
test_df.fillna(value='这是一个null值').show()
- 对不同列的null值进行填充
test_df.fillna(value={'name1':'这是一个NL值','age1':8888}).show()
- 对指定列的null值进行填充
test_df.fillna(value=666,subset=['age1']).show()
2.3.5 替换 – to_replace
df.replace(to_replace=, value=, subset=)
将所有列的值替换
to_replace:需要替换的值
value:替换后的值
subset:指定列
- 替换数据 / 替换指定列的数据
test_df.replace(to_replace=20,value=9999).show()
test_df.replace(to_replace=20,value=8888,subset=['age1']).show()
- 对相同类型列的不同值进行替换, 不支持混合类型替换
# 对相同类型列的不同值进行替换, 不支持混合类型替换
# test_df.replace({'zhangsan':'张三',20:100}).show() # 报错
test_df.replace({'zhangsan':'张三','lisi':'李四'}).show()
- 对指定列的值进行替换
# 对指定列的值进行替换
test_df.replace(to_replace=20,value=5555,subset=['age1','age2']).show()
3. SparkSQL内置函数–字符串函数
数据准备: 导入我们的pyspark中的sql的方法模块
from pyspark.sql import functions as F
from pyspark.sql import SparkSession
# 创建SparkSession对象
ss = SparkSession.builder.getOrCreate()
# 使用sparkcontext读取hdfs上的文件数据
sc = ss.sparkContext
# 将读取的文件数据转化为rdd
rdd = sc.textFile('hdfs://node1:8020/data/stu.txt')
res1 = rdd.collect()
# print(f'rdd文件数据:{res1}')
# 将每行字符串数据切割转为二维rdd
rdd_split = rdd.map(lambda x: x.split(','))
res2 = rdd_split.collect()
# print(f'切割后的rdd数据:{res2}')
# 将rdd转为df数据
df = rdd_split.toDF(
schema='id string,name string,gender string,age string,birthday string,major string,hobby string,create_time string')
# 查看转化的df数据
# df.show()
df = df.select('*').limit(5)
# df.show()
# spark提供了一个functions模块, 里面有一些内置函数
concat(列名1, 列名2, ...)
: 对字符串类型列数据进行拼接concat_ws(拼接符, 列名1, 列名2, ...)
: 以指定的拼接符对字符串类型列数据进行拼接regexp_replace(列名, 正则表达式匹配的子串/需要替换的子串, 替换的子串)
: 替换正则表达式匹配到的子串regexp_extract(列名, 正则表达式分组匹配的子串, 第几组数据)
: 抽取第几组数据split(列名, 分割符/正则表达式)
: 以指定的分割符对字符串类型列数据进行分割, 返回一个列表substring(str=列名, pos=字符串位置, len=字符串长度)
: 对字符串类型列数据从指定位置开始截取指定长度的子串, pos值从1开始substring_index(str=列名, delim=截取符, count=第几个截取符)
:
count的值为正数, 从左往右数第count个截取符, 获取左侧的子串
count的值为负数, 从右往左数第count个截取符, 获取右侧的子串
3.1 拼接操作 – concat / concat_ws
- concat(列名1, 列名2, …):对字符串类型列数据进行拼接
- concat_ws(拼接符, 列名1, 列名2, …):以指定的拼接符对字符串类型列数据进行拼接
# concat(列名1, 列名2, ...): 对字符串类型列数据进行拼接
df.select(F.concat('id','name')).show()
# F.col(列名): 获取列数据
df.select(F.concat('id','name',F.col('gender'))).show()
# concat_ws(拼接符, 列名1, 列名2, ...): 以指定的拼接符对字符串类型列数据进行拼接
df.select(F.concat_ws('*','id','name',F.col('gender'))).show()
3.2 正则表达式
3.2.1 正则表达式替换操作
- egexp_replace(列名, 正则表达式匹配的子串/需要替换的子串, 替换的子串)
# regexp_replace(列名, 正则表达式匹配的子串/需要替换的子串, 替换的子串)
df.select(F.regexp_replace('birthday','-','/')).show()
df.select(F.regexp_replace('birthday',r'\d+','/')).show()
3.2.2 正则表达式抽取操作
- regexp_extract(列名, 正则表达式分组匹配的子串, 第几组数据): 抽取第几组数据
- 通用表达式:regexp_extract(列名, (.?)-(.?)-(.*), 第几组数据)
- 从1开始,为0 的是全部数据
# regexp_extract(列名, 正则表达式分组匹配的子串, 第几组数据): 抽取第几组数据
# regexp_extract(列名, (.*?)-(.*?)-(.*), 第几组数据)
# 从1开始,为0 的是全部数据
df.select(F.regexp_extract('birthday',r'(\d+)-(\d+)-(\d+)',0)).show()
df.select(F.regexp_extract('birthday',r'(\d+)-(\d+)-(\d+)',1)).show()
df.select(F.regexp_extract('birthday',r'(\d+)-(\d+)-(\d+)',2)).show()
df.select(F.regexp_extract('birthday',r'(.*?)-(.*?)-(.*)',3)).show()
3.3 分割操作 – split
- split(列名, 分割符/正则表达式): 以指定的分割符对字符串类型列数据进行分割, 返回一个列表,以所有分隔符进行分割, 返回分割后的列表
- 第二个参数指定返回的数组中元素的数量。如果指定为 1,则只会返回整个分割后的字符串作为单个元素;如果指定为 2,则会返回两个元素,即按照分隔符分割后的两部分。
# split(列名, 分割符/正则表达式): 以指定的分割符对字符串类型列数据进行分割, 返回一个列表
# 以所有分隔符进行分割, 返回分割后的列表
#第二个参数指定返回的数组中元素的数量。如果指定为 1,则只会返回整个分割后的字符串作为单个元素;如果指定为 2,则会返回两个元素,即按照分隔符分割后的两部分。
df.select(F.split('birthday', '-')).show()
df.select(F.split('birthday', '-', 1)).show()
# 以第一个分割符进行分割, 返回分割后的列表
df.select(F.split('birthday', '-', 2)).show()
3.4 截取操作 – substring / substring_index
- substring(str=列名, pos=字符串位置, len=字符串长度): 对字符串类型列数据从指定位置开始截取指定长度的子串
- substring_index(str=列名, delim=截取符, count=第几个截取符)
# substring(str=列名, pos=字符串位置, len=字符串长度): 对字符串类型列数据从指定位置开始截取指定长度的子串
# pos的值从1开始
df.select(F.substring('birthday',1,4)).show()
df.select(F.substring('birthday',0,4)).show()
# substring_index(str=列名, delim=截取符, count=第几个截取符)
# count的值为正数, 从左往右数第count个截取符, 获取左侧的子串
# count的值为负数, 从右往左数第count个截取符, 获取右侧的子串
df.select(F.substring_index('birthday','-',1)).show()
df.select(F.substring_index('birthday','-',-1)).show()
4. SparkSQL内置函数 – 聚合函数
在 PySpark 中,Spark SQL 提供了一系列内置的聚合函数,这些函数可以帮助您执行常见的聚合操作,如计数、求和、平均值、最大值和最小值等。这些函数非常适合处理 DataFrame 中的数据,以生成汇总统计数据。
数据准备:
from pyspark.sql import functions as F
from pyspark.sql import SparkSession
# 创建SparkSession对象
ss = SparkSession.builder.getOrCreate()
# 使用sparkcontext读取hdfs上的文件数据
sc = ss.sparkContext
# 将读取的文件数据转化为rdd
rdd = sc.textFile('hdfs://node1:8020/data/stu.txt')
res1 = rdd.collect()
# print(f'rdd文件数据:{res1}')
# 将每行字符串数据切割转为二维rdd
rdd_split = rdd.map(lambda x: x.split(','))
res2 = rdd_split.collect()
# print(f'切割后的rdd数据:{res2}')
# 将rdd转为df数据
df = rdd_split.toDF(
schema='id string,name string,gender string,age string,birthday string,major string,hobby string,create_time string')
# 查看转化的df数据
# df.show()
df = df.select('*').limit(5)
# df.show()
# spark提供了一个functions模块, 里面有一些内置函数
常用的聚合函数
-
count()
:- 计算非空值的数量。
-
sum()
:- 计算列的总和。
-
avg()
:- 计算列的平均值。
-
max()
和min()
:- 计算列的最大值和最小值。
-
approx_count_distinct()
:- 计算列的近似不同值的数量。
-
collect_list()
:- 收集所有非空值到一个列表中。
-
collect_set()
:- 收集所有不同的非空值到一个集合中。
-
first()
和last()
:- 返回分组中第一个或最后一个非空值。
-
sumDistinct()
:- 计算不同值的总和。
-
kurtosis()
:- 计算列的峰度。
-
skewness()
:- 计算列的偏斜度。
-
stddev()
和stddev_pop()
:- 计算列的标准差。
-
variance()
和var_pop()
:- 计算列的方差。
4.1 对某列聚合操作
F.聚合函数(‘字段’)
print('--------------------对某列聚合操作--------------------')
df.select(F.max('age'),
F.mean('age'),
F.min('age'),
F.sum('id'),
F.count('age'),
F.countDistinct('age')).show()
4.2 分组聚合操作 – groupby
- 对一列进行分组聚合
print('--------------------分组聚合操作--------------------')
# 借助agg函数使用内置的聚合函数实现分组聚合操作
# select gender, avg(age), max(height), min(weight) from df group by gender
# 对一列进行聚合操作
# df_select.groupby('gender').avg('age').alias('avg_age').show()
df.groupby('gender').agg(F.sum('age'),
F.mean('age')).show()
- 对不同列进行不同聚合操作
# 对不同列进行不同聚合操作
df.groupby('gender').agg(F.sum('age').alias('sum'),
F.round(F.mean('age'),2).alias('avg'),
F.max('id').alias('max')).show()
- {列名:函数名, …}-不建议使用
# {列名:函数名, ...}-不建议使用
df.groupby('gender').agg({'age':'sum','id':'max'}).show()
5. SparkSQL内置函数 – 时间函数
数据准备:
from pyspark.sql import functions as F
from pyspark.sql import SparkSession
# 创建SparkSession对象
ss = SparkSession.builder.getOrCreate()
# 使用sparkcontext读取hdfs上的文件数据
sc = ss.sparkContext
# 将读取的文件数据转化为rdd
rdd = sc.textFile('hdfs://node1:8020/data/stu.txt')
res1 = rdd.collect()
# print(f'rdd文件数据:{res1}')
# 将每行字符串数据切割转为二维rdd
rdd_split = rdd.map(lambda x: x.split(','))
res2 = rdd_split.collect()
# print(f'切割后的rdd数据:{res2}')
# 将rdd转为df数据
df = rdd_split.toDF(
schema='id string,name string,gender string,age string,birthday string,major string,hobby string,create_time string')
# 查看转化的df数据
# df.show()
df = df.select('*').limit(5)
# df.show()
# spark提供了一个functions模块, 里面有一些内置函数
时间函数类型:
current_date()
:获取当前的日期类型时间 yyyy-MM-dd
current_timestamp()
:获取当前的日期时间类型时间 yyyy-MM-dd HH:mm:ss.ms
unix_timestamp()
:获取当前的时间戳类型 unix时间戳将日期时间类型转换为指定的格式
date_format(date=,format=)
date: 日期时间类型列数据
format: 指定的日期时间格式将时间戳转换成日期时间类型-
from_unixtime(timestamp=, format=)
timestamp: 时间戳format: 日期时间格式年, 月, 日, 季度, 当月的最后一天日期等
F.year()
F.month()
F.dayofmonth()
F.quarter()
F.hour()
F.minute()
F.second()
F.last_day()
F.dayofweek()
F.dayofyear()
日期+天数
F.date_add(start=,days=)
start: 日期, 列名
days: 天数日期-天数
F.date_sub(start=,days=)
start: 日期, 列名
days: 天数日期+月数
F.add_months(start=, months=)
start: 日期, 列名
months: 月数天数差值=结束日期-开始日期
F.datediff(end=, start=)
end:结束日期, 列名
start:开始日期, 列名
5.1 获取当前时间
- current_date():获取当前的日期类型时间 yyyy-MM-dd
# current_date():获取当前的日期类型时间 yyyy-MM-dd
df.select('id','name',F.current_date().alias('time')).show()
- current_timestamp():获取当前的日期时间类型时间 yyyy-MM-dd HH:mm:ss.ms
# current_timestamp():获取当前的日期时间类型时间 yyyy-MM-dd HH:mm:ss.ms
df.select('id','name',F.current_timestamp().alias('time')).show()
- unix_timestamp():获取当前的时间戳类型 unix时间戳
# unix_timestamp():获取当前的时间戳类型 unix时间戳
df.select('id','name',F.unix_timestamp().alias('time')).show()
5.2 unix时间戳格式化
将时间戳转换成日期时间类型
from_unixtime(timestamp=, format=)
timestamp: 时间戳
format: 日期时间格式
- 使用表的字段,时间戳
print('---------------------------unix时间戳格式化---------------------------')
# 将时间戳转换成日期时间类型
# from_unixtime(timestamp=, format=)
# timestamp: 时间戳
# format: 日期时间格式
df.select(F.from_unixtime('create_time','yyyy-MM-dd').alias('time')).show()
df.select(F.from_unixtime('create_time','yyyy-MM-dd HH:mm:ss').alias('time')).show()
- 如果要直接输入一个整数类型的时间戳,那么首先要使用F.lit(时间戳)先进行转化
F.lit 函数用于创建一个表示常量值的 Column 对象,这在需要将非 Column 类型的数据(如整数或字符串)传递给 SQL 函数时非常有用。
df.select(F.from_unixtime(F.lit(1723037731),'yyyy-MM-dd HH:mm:ss').alias('time')).show()
5.3 日期时间格式化
将日期时间类型转换为指定的格式 date_format(date=,format=)
date: 日期时间类型列数据
format:指定的日期时间格式
# 将日期时间类型转换为指定的格式
# date_format(date=,format=)
# date: 日期时间类型列数据
# format: 指定的日期时间格式
df.select('id','name',F.date_format('birthday','yyyy-MM').alias('time')).show()
df.select('id','name',F.date_format(F.current_timestamp(),'yyyy-MM-dd HH-mm-ss').alias('time')).show()
5.4 获取日期时间部分数据
print('---------------------------获取日期时间部分数据---------------------------')
df.select('birthday',
F.year('birthday').alias('year'),
F.month('birthday').alias('month'),
F.dayofmonth('birthday').alias('day'),
F.quarter('birthday').alias('quarter'),
F.hour('birthday').alias('hour'),
F.minute('birthday').alias('minute'),
F.second('birthday').alias('second'),
F.last_day('birthday').alias('last_day')
).show()
5.5 时间运算
日期+天数
F.date_add(start=,days=)
start: 日期, 列名
days: 天数日期-天数
F.date_sub(start=,days=)
start: 日期, 列名
days: 天数日期+月数
F.add_months(start=, months=)
start: 日期, 列名
months: 月数天数差值=结束日期-开始日期
F.datediff(end=, start=)
end:结束日期, 列名
start:开始日期, 列名
- 日期+天数 ------》 F.date_add(start=,days=)
# 日期+天数
# F.date_add(start=,days=)
# start: 日期, 列名
# days: 天数
df.select('birthday',F.date_add('birthday',5 ).alias('times')).show()
- 日期-天数 ------》 F.date_sub(start=,days=)
# 日期-天数
# F.date_sub(start=,days=)
# start: 日期, 列名
# days: 天数
df.select('birthday',F.date_sub('birthday',5 ).alias('times')).show()
- 日期+月数 ------》 F.add_months(start=, months=)
# 日期+月数
# F.add_months(start=, months=)
# start: 日期, 列名
# months: 月数
df.select('birthday',F.add_months('birthday',2).alias('month')).show()
- 天数差值=结束日期-开始日期 ------》 F.datediff(end=, start=)
# 天数差值=结束日期-开始日期
# F.datediff(end=, start=)
# end:结束日期, 列名
# start:开始日期, 列名
df.select('birthday',F.datediff(F.current_date(),'birthday').alias('days')).show()