Spark学习(7)-SparkSQL函数定义
创始人
2024-03-01 00:19:29

1 SparkSQL 定义UDF函数

在这里插入图片描述

目前在SparkSQL中,仅仅支持UDF和UDAF函数,python仅支持UDF

1.1 定义方式

定义方式有两种:

  1. sparksession.udf.register()
    注册的UDF可以用于DSL和SQL,返回值用于DSL风格,传参内的名字用于SQL风格。

    udf对象 = sparksession.udf.register(参数1,参数2,参数3)
    

    参数1:UDF名称,可用于SQL风格
    参数2:被注册成UDF的方法名
    参数3:声明UDF的返回值类型
    udf对象: 返回值对象,是一个UDF对象,可用于DSL风格

  2. pyspark.sql.functions.udf
    仅能用于DSL风格

    udf对象 = F.udf(参数1, 参数2)
    

    参数1:被注册成UDF的方法名
    参数2:声明UDF的返回值类型
    udf对象: 返回值对象,是一个UDF对象,可用于DSL风格
    其中F是:

    from pyspark.sql import functions as F
    

    其中,被注册成UDF的方法名是指具体的计算方法,如:

    #add就是将要被注册成UDF的方法名
    def add(x, y): x + y
    

1.2 构建一个Interger返回值类型的UDF

# _*_ coding:utf-8 _*_
"""
@Software  :pyspark
@FileName  :01_create_integer_udf.py
@Date      :2022/11/29 16:51
@Author    :wuk
@Description  : 构建一个Integer返回值类型的的UDF
"""
from pyspark.sql import SparkSession, functions
from pyspark.sql.types import IntegerTypeif __name__ == '__main__':spark = SparkSession.builder.master("local[*]")\.appName("test")\.config("spark.sql.shuffle.partitions", 2)\.getOrCreate()sc = spark.sparkContext# 构建一个rddrdd_map = sc.parallelize([1, 2, 3, 4, 5, 6, 7]).map(lambda x: [x])df = rdd_map.toDF(["num"])# TODO 1: 方式1 sparksession.udf.register(), DSL和SQL风格均可以使用# UDF的处理函数def num_ride_10(num):return num * 10# 参数1: 注册的UDF的名称, 这个udf名称, 仅可以用于 SQL风格# 参数2: UDF的处理逻辑, 是一个单独的方法# 参数3: 声明UDF的返回值类型, 注意: UDF注册时候, 必须声明返回值类型, 并且UDF的真实返回值一定要和声明的返回值一致# 返回值对象: 这是一个UDF对象, 仅可以用于 DSL 语法# 当前这种方式定义的UDF, 可以通过参数1的名称用于SQL风格, 通过返回值对象用户DSL风格udf1 = spark.udf.register("udf1",num_ride_10,IntegerType())# SQL风格中使用# selectExpr 以SELECT的表达式执行, 表达式 SQL风格的表达式(字符串)# select方法, 接受普通的字符串字段名, 或者返回值是Column对象的计算df.selectExpr("udf1(num)").show()# DSL 风格中使用# 返回值UDF对象 如果作为方法使用, 传入的参数 一定是Column对象df.select(udf1(df['num'])).show()# TODO 2: 方式2注册, 仅能用于DSL风格udf = functions.udf(num_ride_10, IntegerType())df.select(udf(df['num'])).show()

1.3 注册一个ArrayType(数字\list)类型的返回值UDF

# _*_ coding:utf-8 _*_
"""
@Software  :pyspark
@FileName  :02_create_array_udf.py
@Date      :2022/11/29 17:21
@Author    :wuk
@Description  : 注册一个ArrayType(数字\list)类型的返回值UDF
"""from pyspark.sql import SparkSession, functions
from pyspark.sql.types import StringType, ArrayTypeif __name__ == '__main__':# 0. 构建执行环境入口对象SparkSessionspark = SparkSession.builder.\appName("test").\master("local[*]").\config("spark.sql.shuffle.partitions", 2).\getOrCreate()sc = spark.sparkContext# 构建一个RDDrdd = sc.parallelize([["hadoop spark flink"], ["hadoop flink java"]])df = rdd.toDF(["line"])# 注册UDF, UDF的执行函数定义def split_line(data):return data.split(" ")  # 返回值是一个Array对象# TODO1 方式1 构建UDFudf2 = spark.udf.register("udf1",split_line,ArrayType(StringType()))# DLS风格df.select(udf2(df['line'])).show(truncate=False)# SQL风格df.createTempView("lines")spark.sql("select udf1(line) from lines").show(truncate=False)# TODO 2 方式2的形式构建UDFudf3 = functions.udf(split_line, ArrayType(StringType()))df.select(udf3(df['line'])).show(truncate=False)

注意:
数组或者list类型,可以使用ArrayType来描述,同时需要传入数组内类型。

1.4 注册一个字典类型的返回值UDF

# _*_ coding:utf-8 _*_
"""
@Software  :pyspark
@FileName  :03_create_dict_udf.py
@Date      :2022/11/29 18:15
@Author    :wuk
@Description  : 注册一个字典类型的返回值UDF
"""
import stringfrom pyspark.sql import SparkSession
from pyspark.sql.types import StructType, IntegerType, StringTypeif __name__ == '__main__':# 0. 构建执行环境入口对象SparkSessionspark = SparkSession.builder. \appName("test"). \master("local[*]"). \config("spark.sql.shuffle.partitions", 2). \getOrCreate()sc = spark.sparkContext# 假设 有三个数字  1 2 3  我们传入数字 ,返回数字所在序号对应的 字母 然后和数字结合形成dict返回# 比如传入1 我们返回 {"num":1, "letters": "a"}rdd = sc.parallelize([[1], [2], [3]])df = rdd.toDF(["num"])# 注册UDFdef process(data):return {"num": data, "letters": string.ascii_letters[data]}"""UDF的返回值是字典的话, 需要用StructType来接收"""udf1 = spark.udf.register("udf1", process, StructType().add("num", IntegerType(), nullable=True). \add("letters", StringType(), nullable=True))df.selectExpr("udf1(num)").show(truncate=False)df.select(udf1(df['num'])).show(truncate=False)

注意: 字典类型返回值, 可以用StructType来进行描述,StructType是一个普通的Spark支持的结构化类型
只是可以用在:

  • DF中用于描述Schema
  • UDF中用于描述返回值是字典的数据。

2 SparkSQL 使用窗口函数

2.1 介绍

2.2 语法

在这里插入图片描述

2.3 开窗函数的使用

# coding:utf8
# 演示sparksql 窗口函数(开窗函数)
import string
from pyspark.sql import SparkSession
# 导入StructType对象
from pyspark.sql.types import ArrayType, StringType, StructType, IntegerType
import pandas as pd
from pyspark.sql import functions as Fif __name__ == '__main__':spark = SparkSession.builder. \appName("create df"). \master("local[*]"). \config("spark.sql.shuffle.partitions", "2"). \getOrCreate()sc = spark.sparkContextrdd = sc.parallelize([('张三', 'class_1', 99),('王五', 'class_2', 35),('王三', 'class_3', 57),('王久', 'class_4', 12),('王丽', 'class_5', 99),('王娟', 'class_1', 90),('王军', 'class_2', 91),('王俊', 'class_3', 33),('王君', 'class_4', 55),('王珺', 'class_5', 66),('郑颖', 'class_1', 11),('郑辉', 'class_2', 33),('张丽', 'class_3', 36),('张张', 'class_4', 79),('黄凯', 'class_5', 90),('黄开', 'class_1', 90),('黄恺', 'class_2', 90),('王凯', 'class_3', 11),('王凯杰', 'class_1', 11),('王开杰', 'class_2', 3),('王景亮', 'class_3', 99)])schema = StructType().add("name", StringType()). \add("class", StringType()). \add("score", IntegerType())df = rdd.toDF(schema)# 窗口函数只用于SQL风格, 所以注册表先df.createTempView("stu")# TODO 聚合窗口spark.sql("""SELECT *, AVG(score) OVER() AS avg_score FROM stu""").show()# SELECT *, AVG(score) OVER() AS avg_score FROM stu 等同于# SELECT * FROM stu# SELECT AVG(score) FROM stu# 两个SQL的结果集进行整合而来spark.sql("""SELECT *, AVG(score) OVER(PARTITION BY class) AS avg_score FROM stu""").show()# SELECT *, AVG(score) OVER(PARTITION BY class) AS avg_score FROM stu 等同于# SELECT * FROM stu# SELECT AVG(score) FROM stu GROUP BY class# 两个SQL的结果集进行整合而来# TODO 排序窗口spark.sql("""SELECT *, ROW_NUMBER() OVER(ORDER BY score DESC) AS row_number_rank, DENSE_RANK() OVER(PARTITION BY class ORDER BY score DESC) AS dense_rank, RANK() OVER(ORDER BY score) AS rankFROM stu""").show()# TODO NTILEspark.sql("""SELECT *, NTILE(6) OVER(ORDER BY score DESC) FROM stu""").show()

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...