spark--Spark SQL自定义函数-★★★★★

  • 之前hive中也学习过自定义函数

1.UDF(User-Defined-Function)–SparkSQL支持自定义–最常用

  • DSL风格 val small2big1: UserDefinedFunction = functions.udf((word:String)=>{word.toUpperCase})//定义方法
  • SQL风格 spark.udf.register(“small2big2”,(word:String)=>{word.toUpperCase})//注册UDF
  • 即最基本的自定义函数,类似to_char,to_date
  • 输入一行,输出一行

2 .UDAF(User-Defined Aggregation Funcation)–SparkSQL支持自定义

  • 用户自定义聚合函数,类似在group by之后使用的sum,avg
  • 输入多行,输出一行

3.UDTF(User-Defined Table-Generating Functions)–SparkSQL不支持自定义UDTF

  • 用户自定义生成函数,有点像flatMap
  • 输入一行,输出多行
package cn.hanjiaxiaozhi.sql
​
import org.apache.spark.SparkContext
import org.apache.spark.sql.expressions.UserDefinedFunction
import org.apache.spark.sql.{DataFrame, Dataset, SparkSession, functions}/**
 * Author hanjiaxiaozhi
 * Date 2020/7/25 10:21
 * Desc 演示使用SparkSQL完成自定义UDF函数
 * 需求: 将表中的单词转为大写
 */
object UDFDemo {
  def main(args: Array[String]): Unit = {
    //0.准环境和数据
    val spark: SparkSession = SparkSession.builder().appName("sql").master("local[*]").getOrCreate()
    val sc: SparkContext = spark.sparkContext
    sc.setLogLevel("WARN")
    import spark.implicits._
​
    //可以使用sc.textFile("路径")进行读取,然后返回RDD,再转为DataFrame/DataSet
    //也可以直接使用SparkSession的读取方法直接返回DataFrame/DataSet
    val df: DataFrame = spark.read.text("D:\\data\\spark\\udf.txt")
    df.show(false)
    /*
     * +----------+
     * |value     |
     * +----------+
     * |helloworld|
     * |abc       |
     * |study     |
     * |smallWORD |
     * +----------+
     *///定义UDF函数并使用UDF函数将数据转为大写
    //TODO 1 DSL风格
    //定义自定义UDF
    import org.apache.spark.sql.functions._
    val small2big1: UserDefinedFunction = udf((word:String)=>{word.toUpperCase})
    //注意:自定义函数中的参数为value列对应的单词,所以应该写$"value",而不是value
    df.select($"value",small2big1($"value")).show(false)
​
​
    //TODO 2 SQL风格
    df.createOrReplaceTempView("t_word")//注册表名
    //定义一个自定义的UDF函数,可以接收一个String并转为大写
    spark.udf.register("small2big2",(word:String)=>{word.toUpperCase})//注册UDF
    val sql:String =
      """
        |select value,small2big2(value) 
        |from t_word
        |""".stripMargin//编写sql并使用UDF
    spark.sql(sql).show(false)//执行sql
  }
}

4.自定义UDAF

  • l 需求
有udaf.json格式数据内容如下

{"name":"Michael","salary":3000}

{"name":"Andy","salary":4500}

{"name":"Justin","salary":3500}

{"name":"Berta","salary":4000}
求取平均工资
  • l 方法重写说明
inputSchema:输入数据的类型

bufferSchema:产生中间结果的数据类型

dataType:最终返回的结果类型

deterministic:确保一致性(输入什么类型的数据就返回什么类型的数据),一般用true

initialize:指定初始值

update:每有一条数据参与运算就更新一下中间结果(update相当于在每一个分区中的运算)

merge:全局聚合(将每个分区的结果进行聚合)

evaluate:计算最终的结果
  • l 代码演示
package cn.hanjiaxiaozhi.sql

import org.apache.spark.SparkContext
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._
import org.apache.spark.sql.{DataFrame, Row, SparkSession}


object UDAFDemo {
  def main(args: Array[String]): Unit = {
    //1.获取sparkSession
    val spark: SparkSession = SparkSession.builder().appName("SparkSQL").master("local[*]").getOrCreate()
    val sc: SparkContext = spark.sparkContext
    sc.setLogLevel("WARN")
    //2.json
    val employeeDF: DataFrame = spark.read.json("D:\\data\\sql\\udaf.json")
    //3.创建临时表
    employeeDF.createOrReplaceTempView("t_employee")
    //4.注册UDAF函数
    spark.udf.register("avgsalary",new SparkFunctionUDAF)
    //5.使用自定义UDAF函数
    spark.sql("select avgsalary(salary) from t_employee").show()
    //6.使用内置的avg函数
    spark.sql("select avg(salary) from t_employee").show()

  }
}
class SparkFunctionUDAF extends UserDefinedAggregateFunction{
  //输入的数据类型的schema
  override def inputSchema: StructType = {
     StructType(StructField("input",LongType)::Nil)
  }
  //缓冲区数据类型schema,就是转换之后的数据的schema
  override def bufferSchema: StructType = {
    StructType(StructField("sum",LongType)::StructField("total",LongType)::Nil)
  }
  //返回值的数据类型
  override def dataType: DataType = {
    DoubleType
  }
  //确定是否相同的输入会有相同的输出
  override def deterministic: Boolean = {
    true
  }
  //初始化内部数据结构
  override def initialize(buffer: MutableAggregationBuffer): Unit = {
    buffer(0) = 0L
    buffer(1) = 0L
  }
  //更新数据内部结构
  override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
    //所有的金额相加
    buffer(0) = buffer.getLong(0) + input.getLong(0)
    //一共有多少条数据
    buffer(1) = buffer.getLong(1) + 1
  }
  //来自不同分区的数据进行合并
  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): Any = {
    buffer.getLong(0).toDouble / buffer.getLong(1)
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是关于spark-sql、复杂sql、函数、自定义函数的回复: Spark SQLSpark中的一个模块,它提供了一种基于结构化数据的编程接口,可以使用SQL语句来查询和操作数据。Spark SQL支持多种数据源,包括Hive、JSON、Parquet等。 复杂SQL是指包含多个子查询、联合查询、嵌套查询等复杂结构的SQL语句。这种SQL语句通常需要使用多种SQL语法和技巧来实现,例如使用WITH语句、子查询、JOIN操作等。 函数是SQL语言中的一种基本元素,它可以接受输入参数并返回一个值。SQL语言中内置了许多函数,例如聚合函数、字符串函数、日期函数等。 自定义函数是指用户可以根据自己的需求编写的函数,它可以扩展SQL语言的功能。在Spark SQL中,用户可以使用Scala或Java编写自定义函数,并将其注册到Spark SQL中,从而可以在SQL语句中使用。 希望以上回复能对您有所帮助。 ### 回答2: 2020年11月23日,Spark SQL 及其相关技术迎来了新的进展。首先是Spark SQL继续发扬自身强大的复杂查询能力,以支持更为灵活、多样化的业务需求。而这背后,离不开Spark SQL强大的函数库和高度可扩展、易于定制的自定义函数(UDF)机制。 随着数据规模的不断增大,针对大规模复杂数据的查询需求也变得越来越复杂,针对这类需求,我们需要更为高级的 SQL 开发技巧和工具。在Spark SQL中,复杂 SQL 查询能够高效地进行大规模数据处理和分析,并建立更为稳健和精准的业务分析模型。因此,Spark SQL 在大规模数据查询分析领域的地位越来越重要。 而为了更好地实现此目标,随着Spark SQL的发展,它提供的函数和UDF(User-Defined Functions)也越来越强大和方便。基于 Spark SQL 强大的函数库,我们可以轻松实现各种复杂查询和分析操作,并且能够在多种语言和环境中快速支持标准和自定义函数的扩展。同时,Spark SQL 提供了高度可扩展、易于定制的自定义函数(UDF)机制,从而使得用户可以根据自身需求,快速创建符合业务要求的函数。 在 2020 年 11 月 23 日这一天,Spark SQL 又进一步加强了其自身的函数库和UDF机制,从而为数据分析、深度学习、机器学习等应用场景带来更大的便利性和高效性。在未来,我们相信,Spark SQL 和其强大的函数库与UDF机制,将会成为更多人进行大规模数据处理与分析的首选工具,也将进一步拓宽大规模分布式计算领域的发展空间! ### 回答3: 2020年11月23日,主要涉及四个方面的内容:Spark-SQL、复杂SQL、函数和自定义函数Spark-SQL是基于Spark框架下的一种SQL查询语言,它能够通过结构化的方式轻松地处理大数据,同时也具备了SQL灵活的查询能力。Spark-SQL通过对数据进行特定的格式化后,将其以类似于表的格式暴露给普通SQL查询。Spark-SQL支持大部分标准SQL的语法,同时也支持使用Java、Scala、Python等编程语言进行查询。 复杂SQL是指具备较高难度、较复杂查询、涉及多个数据表和复杂条件限制的SQL语句。常见的复杂SQL包括嵌套查询(Subquery)、联合查询(Union)、连接查询(Join)等。对于复杂SQL的处理,需要使用到一些高级查询和优化技巧,如索引的使用、SQL查询计划的优化等。 函数是SQL查询过程中常用的一种结构,它可以帮助我们实现某些常用的逻辑和计算。SQL中内置了很多函数,如求和函数Sum、平均数函数Avg等。此外,SQL还支持使用用户自定义函数来实现某些特定的计算和操作。使用自定义函数,可以提高程序的效率,提供更多操作的逻辑控制。 自定义函数是指,通过编写程序来实现一些特定的操作和计算,并将其封装为函数以便于经常使用。对于Spark-SQL,可以通过编写一些Java或Scala代码,然后打包为JAR文件,供Spark中的SQL查询使用。自定义函数的使用需要注意函数的输入输出格式、函数的逻辑控制等方面,以保证函数的正确性和高效性。 综上所述,2020年11月23日的主要内容与Spark-SQL、复杂SQL、函数和自定义函数有关,这些内容都是SQL查询过程中常用的一些基础和高级功能,可以帮助我们实现各种复杂的数据查询和数据处理操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值