【问题标题】:Spark Sql udf with variable number of parametersSpark Sql udf,参数数量可变
【发布时间】:2025-12-27 05:00:07
【问题描述】:

我想要一个用于 Spark Sql 的 concat 函数。 我写了一个udf为

sqlContext.udf.register("CONCAT",(args:String*)=>{
 String out=""
 for(arg<-args)
  {
    out+=arg
  }
 out
})

sqlContext.sql("select col1,col2,CONCAT(col1,col2) from testtable")

但是这个 udf 不起作用,我遇到了一个异常。 如果我尝试使用固定数量的参数,那么它可以工作。 我正在使用 spark 1.3.1 和 scala 2.10.5。

有没有人遇到过这个问题或知道解决方案?

【问题讨论】:

  • 能否提供问题中的例外情况?

标签: scala apache-spark apache-spark-sql


【解决方案1】:

您可以使用struct 函数执行此操作,如下所示:

val myUDF = udf {
  (r: Row) => r.toSeq.map(...) // the "r" row contains your arguments
}
val df = ....
df.select(col("col1"), myUDF(struct(col("col2"), col("col3"), col("col4"), ...)))

【讨论】:

    【解决方案2】:

    如果您只想使用原始 SQL 连接列,则根本不需要自定义 UDF。 CONCAT 函数已经存在:

    val df = sc.parallelize(List(("a", "b", "c"))).toDF("x", "y", "z")
    df.registerTempTable("df")
    sqlContext.sql("SELECT CONCAT(x, y, z) AS xyz FROM df").show
    
    // +---+
    // |xyz|
    // +---+
    // |abc|
    // +---+
    

    从 1.5.0 开始你可以直接使用concat / concat_ws 函数:

    import org.apache.spark.sql.functions.{concat, concat_ws}
    
    df.select(concat_ws("-", $"x", $"y", $"z").alias("x-y-z")).show
    // +-----+
    // |x-y-z|
    // +-----+
    // |a-b-c|
    // +-----+
    
    df.select(concat($"x", $"y", $"z").alias("xyz")).show
    
    // +---+
    // |xyz|
    // +---+
    // |abc|
    // +---+
    

    另见Spark UDF with varargs

    【讨论】: