Spark SQL 内置函数

这篇具有很好参考价值的文章主要介绍了Spark SQL 内置函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、Spark SQL内置函数

(一)内置函数概述

1、10类内置函数

Spark SQL内置了大量的函数,位于API org.apache.spark.sql.functions中。这些函数主要分为10类:UDF函数、聚合函数、日期函数、排序函数、非聚合函数、数学函数、混杂函数、窗口函数、字符串函数、集合函数,大部分函数与Hive中相同。

2、两种使用方式

使用内置函数有两种方式:一种是通过编程的方式使用;另一种是在SQL语句中使用。

(二)内置函数演示

读取HDFS上的people.json,得到数据帧,执行命令:val peopleDF = spark.read.json(“hdfs://master:9000/datasource/input/people.json”)
Spark SQL 内置函数
显示数据帧内容,执行命令:peopleDF.show()
Spark SQL 内置函数
导入Spark SQL内置函数,执行命令:import org.apache.spark.sql.functions._
Spark SQL 内置函数

1、通过编程方式使用内置函数upper()

利用upper()函数将姓名转成大写,执行命令:peopleDF.select(upper(col(“name”)).as(“name”)).show()
Spark SQL 内置函数
上述代码中,使用select()方法传入需要查询的列,使用as()方法指定列的别名。代码col(“name”)指定要查询的列,也可以使用 $"name" 代替,但是需要导入import spark.implicits._,执行命令:peopleDF.select(upper($"name").as("name")).show()
Spark SQL 内置函数
对某列使用了内置函数,如果还要显示其它列,就会报错
Spark SQL 内置函数

2、通过SQL语句的方式使用内置函数upper()

定义临时视图,执行命令:peopleDF.createTempView("t_people")
Spark SQL 内置函数
执行命令:spark.sql(“select upper(name) as name from t_people”).show()
Spark SQL 内置函数
执行命令:spark.sql(“select upper(name) as name, age from t_people”).show()
Spark SQL 内置函数

3、演示其它内置函数的使用

打印Schema信息,执行命令:peopleDF.printSchema()
Spark SQL 内置函数
查询name列,执行命令:peopleDF.select(“name”).show()
Spark SQL 内置函数
可用SQL语句方式来完成同样的任务
Spark SQL 内置函数
查询name列和age列,其中将age列的值增加1,执行命令:peopleDF.select($"name", $"age" + 1).show()
Spark SQL 内置函数
可用SQL语句方式来完成同样的任务
Spark SQL 内置函数
查询年龄大于21的记录,执行命令:peopleDF.filter($"age" > 21).show()
Spark SQL 内置函数
可用SQL语句方式来完成同样的任务
Spark SQL 内置函数
根据age进行分组,并求每一组的数量,执行命令:peopleDF.groupBy("age").count().show()
Spark SQL 内置函数
可用SQL语句方式来完成同样的任务
Spark SQL 内置函数

二、自定义函数

(一)自定义函数概述

当Spark SQL提供的内置函数不能满足查询需求时,用户可以根据自己的业务编写自定义函数(User Defined Functions,UDF),然后在Spark SQL中调用。

(二)演示自定义函数

1、提出任务:手机号保密

有这样一个需求:为了保护用户的隐私,当查询数据的时候,需要将用户手机号的中间4位用星号()代替,比如手机号147***9205。这时就可以写一个自定义函数来实现这个需求。

2、编写程序,完成任务

创建SparkSQLUDF单例对象
Spark SQL 内置函数

package net.army.sql.day01

import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}

/**
 * 功能:演示自定义函数
 * 日期:2023年06月14日
 * 作者:梁辰兴
 */
object SparkSQLUDF {
  def main(args: Array[String]): Unit = {
    // 创建或得到SparkSession
    val spark = SparkSession.builder()
      .appName("SparkSQLUDF")
      .master("local[*]")
      .getOrCreate()

    // 第一步:创建测试数据(亦可读取文件)
    // 创建电话模拟数据
    val arr = Array("15892925678", "13567892345", "18034561290", "13967678901")
    // 将数组转换成RDD
    val rdd: RDD[String] = spark.sparkContext.makeRDD(arr)
    // 将RDD[String]转为RDD[Row]
    val rowRDD: RDD[Row] = rdd.map(line => Row(line))
    // 定义数据的schema
    val schema = StructType(
      List {
        StructField("phone", StringType, true)
      }
    )
    // 将RDD[Row]转为DataFrame
    val df = spark.createDataFrame(rowRDD, schema)

    // 第二步:创建自定义函数(phoneHide)
    val phoneUDF = (phone: String) => {
      var result = "手机号码错误!"
      if (phone != null && phone.length == 11) {
        val buffer = new StringBuffer()
        buffer.append(phone.substring(0, 3))
        buffer.append("****")
        buffer.append(phone.substring(7))
        result = buffer.toString
      }
      result
    }
    // 注册函数(第一个参数为函数名称,第二个参数为自定义的函数)
    spark.udf.register("phoneHide", phoneUDF)

    // 第三步:调用自定义函数
    // 创建临时视图
    df.createTempView("t_phone")
    // 查询表,调用自定义函数处理phone字段
    spark.sql("select phoneHide(phone) as phone from t_phone").show()
  }
}

上述代码通过spark.udf.register()方法注册一个自定义函数phoneHide,然后使用spark.sql()方法传入SQL语句,在SQL语句中调用自定义函数phoneHide并传入指定的列,该列的每一个值将依次被自定义函数phoneHide处理。

运行程序,查看结果
Spark SQL 内置函数

三、自定义聚合函数

(一)自定义聚合函数概述

Spark SQL提供了一些常用的聚合函数,如count()、countDistinct()、avg()、max()、min()等。此外,用户也可以根据自己的业务编写自定义聚合函数(User Defined AggregateFunctions,UDAF)。

UDF主要是针对单个输入返回单个输出,而UDAF则可以针对多个输入进行聚合计算返回单个输出,功能更加强大。

(二)演示自定义聚合函数

1、提出任务:实现求员工平均工资功能的UDAF

员工工资数据存储于HDFS上/input目录里的employees.json文件中
Spark SQL 内置函数

{"name", "Army", "salary": 3500}
{"name", "Brown", "salary": 4500}
{"name", "Alice", "salary": 3200}
{"name", "Jenny", "salary": 5500}
{"name", "Mike", "salary": 6500}

2、编写程序,完成任务

创建MyAverage类,继承UserDefinedAggregateFunction类

Spark SQL 内置函数

package net.army.sql.day01

import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types.{DataType, DoubleType, LongType, StructField, StructType}

/**
 * 功能:自定义聚合函数类,求平均值
 * 日期:2023年06月14日
 * 作者:梁辰兴
 */
class MyAverage extends UserDefinedAggregateFunction {
  // 聚合函数输入参数的类型,运行时会将需要聚合的每一个值输入聚合函数中
  // inputColumn为输入的列名,不做特殊要求,相当于一个列占位符
  override def inputSchema: StructType = StructType (
    List(StructField("inputColumn", LongType))
  )

  // 定义存储聚合运算产生的中间数据的Schema
  // sum和count不作特殊要求,为自定义名称
  override def bufferSchema: StructType = StructType(
    List(
      StructField("sum", LongType), // 参与聚合的数据总和
      StructField("count", LongType) // 参与聚合的数据数量
    )
  )

  // 定义数据类型
  override def dataType: DataType = DoubleType

  // 针对给定的同一组输入,聚合函数是否返回相同的结果,通常为true
  override def deterministic: Boolean = true

  // 初始化聚合运算的中间结果,中间结果存储于buffer中,buffer是一个Row类型
  override def initialize(buffer: MutableAggregationBuffer): Unit = {
    buffer(0) = 0L // 与bufferSchema中的第一个字段(sum)对应,即sum的初始值
    buffer(1) = 0L // 与bufferSchema中的第二个字段(count)对应,即count的初始值
  }

  // 由于参与聚合的数据会依次输入聚合函数,因此每当向聚合函数输入新的数据时,都会调用该函数更新聚合中间结果
  override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
    if (!input.isNullAt(0)) {
      buffer(0) = buffer.getLong(0) + input.getLong(0) // 更新参与聚合的数据总和
      buffer(1) = buffer.getLong(1) + 1 // 更新参与聚合的数据数量
    }
  }

  // 合并多个分区的buffer中间结果(分布式计算,参与聚合的数据存储于多个分区,每个分区都会产生buffer中间结果
  override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
    buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0) // 合并参与聚合的数据总和
    buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1) // 合并参与聚合的数据数量
  }

  // 计算最终结果,数据总和 / 数据数量 = 平均值
  override def evaluate(buffer: Row): Double = buffer.getLong(0).toDouble / buffer.getLong(1)
}

/**
 * 测试自定义聚合函数
 */
object MyAverage {
  def main(args: Array[String]): Unit = {
    // 创建或得到SparkSession
    val spark = SparkSession.builder()
      .appName("SparkSQLUDF")
      .master("local[*]")
      .getOrCreate()

    // 注册自定义聚合函数
    spark.udf.register("myAverage", new MyAverage)
    // 读取员工JSON数据
    val df = spark.read.json("hdfs://master:9000/input/employees.json")
    // 显示数据帧内容
    df.show()
    // 创建临时视图
    df.createOrReplaceTempView("employees")
    // 调用聚合函数进行查询
    val result = spark.sql("select myAverage(salary) as average_salary from employees")
    // 显示查询结果
    result.show()

    // 停止会话
    spark.toString
  }
}

四、开窗函数

(一)开窗函数概述

row_number()开窗函数是Spark SQL中常用的一个窗口函数,使用该函数可以在查询结果中对每个分组的数据,按照其排序的顺序添加一列行号(从1开始),根据行号可以方便地对每一组数据取前N行(分组取TOPN)。

(二)开窗函数使用格式

row_number() over (partition by 列名 order by 列名 desc) 行号列别名
partition by:按照某一列进行分组

order by:分组后按照某一列进行组内排序

desc:降序,默认升序

(三)开窗函数案例演示

1、提出任务:统计前3名

统计每一个产品类别的销售额前3名(相当于分组求TOPN)

2、编写程序,实现功能,完成任务

创建SparkSQLWindowFunctionDemo单例对象
Spark SQL 内置函数

package net.army.sql.day01

import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}

/**
 * 功能:统计每一个产品类别的销售额前3名
 * 日期:2023年06月14日
 * 作者:梁辰兴
 */
object SparkSQLWindowFunctionDemo {
  def main(args: Array[String]): Unit = {
    // 创建或得到SparkSession
    val spark = SparkSession.builder()
      .appName("SparkSQLUDF")
      .master("local[*]")
      .getOrCreate()

    // 第一步:创建测试数据(字段:日期、产品类别、销售额)
    val arr = Array(
      "2022-05-10,A,710",
      "2022-05-10,B,530",
      "2022-05-10,C,670",
      "2022-05-11,A,520",
      "2022-05-11,B,730",
      "2022-05-11,C,610",
      "2022-05-12,A,500",
      "2022-05-12,B,700",
      "2022-05-12,C,650",
      "2022-05-13,A,620",
      "2022-05-13,B,690",
      "2022-05-13,C,700",
      "2022-05-14,A,720",
      "2022-05-14,B,680",
      "2022-05-14,C,590"
    )
    // 转为RDD[Row]
    val rowRDD = spark.sparkContext
      .makeRDD(arr)
      .map(line => Row(
        line.split(",")(0),
        line.split(",")(1),
        line.split(",")(2).toInt
      ))
    // 构建数据帧元数据
    val structType = StructType(
      List(
        StructField("date", StringType, true),
        StructField("type", StringType, true),
        StructField("money", IntegerType, true)
      ))
    // 将RDD[Row]转成数据帧
    val df = spark.createDataFrame(rowRDD, structType)

    // 第二步:使用开窗函数取每个类别的金额前3名
    // 创建临时视图
    df.createTempView("t_sales")
    // 执行SQL查询,显示每个类别排名
    spark.sql(
      """
        |select date, type, money,
        |        row_number() over (partition by type order by money desc) rank
        |        from t_sales
        |""".stripMargin
    ).show()

    // 执行SQL查询,取每个类别前3名
    spark.sql(
      """
        |select date, type, money, rank from
        |  (
        |     select date, type, money,
        |        row_number() over (partition by type order by money desc) rank
        |        from t_sales
        |  ) sale
        |where sale.rank <= 3
        |""".stripMargin
    ).show()
  }
}

运行程序,查看结果
Spark SQL 内置函数文章来源地址https://www.toymoban.com/news/detail-491549.html

到了这里,关于Spark SQL 内置函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spark 7:Spark SQL 函数定义

    SparkSQL 定义UDF函数 方式1语法: udf对象 = sparksession.udf.register(参数1,参数2,参数3) 参数1:UDF名称,可用于SQL风格 参数2:被注册成UDF的方法名 参数3:声明UDF的返回值类型 udf对象: 返回值对象,是一个UDF对象,可用于DSL风格 方式2语法: udf对象 = F.udf(参数1, 参数2) 参数

    2024年02月11日
    浏览(35)
  • flinksql 流表转换, 自定义udf/udtf,SQL 内置函数及自定义函数

    1、在大多数情况下,用户定义的函数必须先注册,然后才能在查询中使用。不需要专门为 Scala 的 Table API 注册函数。 2、函数通过调用 registerFunction()方法在 TableEnvironment 中注册。当用户定义的函数 被注册时,它被插入到 TableEnvironment 的函数目录中, 这样 Table API 或 SQL 解

    2024年02月22日
    浏览(40)
  • Spark SQL函数定义

    目录 窗口函数 SQL函数分类 Spark原生自定义UDF函数 Pandas的UDF函数 Apache Arrow框架基本介绍 基于Arrow完成Pandas DataFrame和Spark DataFrame互转 基于Pandas完成UDF函数  自定义UDF函数 自定义UDAF函数 分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx]) 分析函数可以大致分成如

    2024年01月21日
    浏览(65)
  • Spark_SQL函数定义(定义UDF函数、使用窗口函数)

                        一、UDF函数定义         (1)函数定义         (2)Spark支持定义函数         (3)定义UDF函数                 (4)定义返回Array类型的UDF         (5)定义返回字典类型的UDF 二、窗口函数         (1)开窗函数简述         (2)

    2024年02月03日
    浏览(34)
  • 16 | Spark SQL 的 UDF(用户自定义函数)

    UDF(用户自定义函数) :Spark SQL 允许用户定义自定义函数,以便在 SQL 查询或 DataFrame 操作中使用。这些 UDF 可以扩展 Spark SQL 的功能,使用户能够执行更复杂的数据操作。 示例:

    2024年02月10日
    浏览(33)
  • Spark SQL示例用法所有函数示例权威详解一【建议收藏】

    Spark中所有功能的入口点是 SparkSession 类。要创建一个基本的 SparkSession ,只需使用 SparkSession.builder() : 完整示例代码可在Spark存储库的“examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala”中找到。 在Spark 2.0中, SparkSession 提供了 对Hive功能的内置支持 ,包括 使用Hi

    2024年02月05日
    浏览(40)
  • spark-sql处理json字符串的常用函数

    整理了spark-sql处理json字符串的几个函数: 1 get_json_object 解析不含数组的 json   2 from_json  解析json 3 schema_of_json 提供生成json格式的方法 4 explode   把JSONArray转为多行 get_json_object(string json_string, string path) :适合最外层为{}的json解析。  第一个参数是json对象变量,也就是含j

    2023年04月08日
    浏览(31)
  • 44、Flink之module模块介绍及使用示例和Flink SQL使用hive内置函数及自定义函数详细示例--网上有些说法好像是错误的

    一、Flink 专栏 Flink 专栏系统介绍某一知识点,并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分,比如术语、架构、编程模型、编程指南、基本的datastream api用法、四大基石等内容。 3、

    2024年02月09日
    浏览(30)
  • 【SQL刷题】Day10----SQL高级过滤函数专项练习

    博主昵称:跳楼梯企鹅 博主主页面链接: 博主主页传送门 博主专栏页面连接: 专栏传送门--网路安全技术 创作初心:本博客的初心为与技术朋友们相互交流,每个人的技术都存在短板,博主也是一样,虚心求教,希望各位技术友给予指导。 博主座右铭:发现光,追随光,

    2023年04月09日
    浏览(37)
  • 在 SQL Server 中,可以使用加号运算符(+)来拼接字符串。但是,如果需要拼接多个字符串或表中的字段,就需要使用内置的拼接函数了

    以下是 SQL Server 中的一些内置拼接函数: 1. CONCAT:将两个或多个字符串拼接在一起。语法为: 示例: 2. CONCAT_WS:与 CONCAT 类似,但可以指定一个分隔符。语法为: 示例: 3. CONCATN:将多个字符串拼接在一起,并在每个字符串之间添加指定的字符。语法为: 示例: 4. REPLAC

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包