在Spark-SQL中创建用户定义的函数

时间:2014-07-30 07:32:55

标签: sql apache-spark

我是新来的火花和火花sql,我试图使用spark SQL查询一些数据。

我需要从以字符串形式给出的日期中获取月份。

我认为不可能直接从sparkqsl查询月份,所以我想在scala中编写用户定义的函数。

是否有可能在sparkSQL中编写udf,如果可能,任何人都可以提出编写udf的最佳方法。

请帮忙

3 个答案:

答案 0 :(得分:11)

如果您愿意使用语言集成查询,则可以执行此操作,至少是为了过滤。

对于包含以下内容的数据文件dates.txt:

one,2014-06-01
two,2014-07-01
three,2014-08-01
four,2014-08-15
five,2014-09-15

你可以根据需要在你的UDF中打包尽可能多的Scala日期魔法,但我会保持简单:

def myDateFilter(date: String) = date contains "-08-"

全部设置如下 - 其中很多来自Programming guide

val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext._

// case class for your records
case class Entry(name: String, when: String)

// read and parse the data
val entries = sc.textFile("dates.txt").map(_.split(",")).map(e => Entry(e(0),e(1)))

您可以将UDF用作WHERE子句的一部分:

val augustEntries = entries.where('when)(myDateFilter).select('name, 'when)

并查看结果:

augustEntries.map(r => r(0)).collect().foreach(println)

请注意我使用的where方法的版本,在doc中声明如下:

def where[T1](arg1: Symbol)(udf: (T1) ⇒ Boolean): SchemaRDD

因此,UDF只能接受一个参数,但您可以编写多个.where()调用来过滤多个列。

编辑Spark 1.2.0(实际上也是1.1.0)

虽然它没有真正记录,但Spark现在支持注册UDF,因此可以从SQL查询。

上述UDF可以使用以下方式注册:

sqlContext.registerFunction("myDateFilter", myDateFilter)

如果表已注册

sqlContext.registerRDDAsTable(entries, "entries")

可以使用

进行查询
sqlContext.sql("SELECT * FROM entries WHERE myDateFilter(when)")

有关详细信息,请参阅this example

答案 1 :(得分:2)

在Spark 2.0中,您可以这样做:

// define the UDF
def convert2Years(date: String) = date.substring(7, 11)
// register to session
sparkSession.udf.register("convert2Years", convert2Years(_: String))
val moviesDf = getMoviesDf // create dataframe usual way
moviesDf.createOrReplaceTempView("movies") // 'movies' is used in sql below
val years = sparkSession.sql("select convert2Years(releaseDate) from movies")

答案 2 :(得分:1)

PySpark 1.5 及以上版本中,我们可以使用内置函数轻松实现此目的。

以下是一个例子:

raw_data = 
[

("2016-02-27 23:59:59", "Gold", 97450.56),

("2016-02-28 23:00:00", "Silver", 7894.23),

("2016-02-29 22:59:58", "Titanium", 234589.66)]


Time_Material_revenue_df  = 
sqlContext.createDataFrame(raw_data, ["Sold_time", "Material", "Revenue"])

from pyspark.sql.functions import  *

Day_Material_reveneu_df = Time_Material_revenue_df.select(to_date("Sold_time").alias("Sold_day"), "Material", "Revenue")