我有一个问题案例,根据输入日期迭代最近36个月。目前使用Scala,通过DataFrame
我得到时间戳字段的最大值。例如:
val vGetDate = hc.read.format("filodb.spark").option("database","YYYYY").option("dataset","XXX").load().agg(max("inv_date").alias("max_date"))
例如,日期为2017-12-01 00:00:00
。
现在我需要迭代才能获得过去36个月的日期。
注意,我使用Spark 1.4而不是Cassandra和FiloDB。
答案 0 :(得分:0)
如果您可以访问Spark 1.5+,则可以使用year
和month
功能轻松实现,但由于您只能访问Spark 1.4,因此您必须复制其功能在UDF中,如下:
val year = udf {
(s: String) =>
java.sql.Timestamp.valueOf(s).getYear
}
val month = udf {
(s: String) =>
java.sql.Timestamp.valueOf(s).getMonth
}
def monthDiff(a: Column, b: Column): Column =
(year(a) - year(b)) * 12 + (month(a) - month(b))
然后,您可以将此UDF与where
子句一起使用,以便在此示例中过滤您的DataFrame
:
final case class Data(date: String)
val df = spark.createDataFrame(Seq(Data("2017-04-01 00:00:00")))
val since = lit("2018-01-01 00:00:00")
assert(df.where(monthDiff(since, $"date") < 36).count == 1)
assert(df.where(monthDiff(since, $"date") < 4).count == 0)
关于迭代的需求,使用Spark DataFrame API时通常要采用的是声明性方法,使用groupBy
语句进行聚合你的钥匙。例如,您的原始查询可以表示如下():
val vGetDate =
hc.read.format("filodb.spark").option("database","YYYYY").option("dataset","XXX").load().
where(monthDiff(lit(startDate), "inv_date")).
groupBy(concat(year("inv_date"), lit("-"), lpad(month("inv_date"), 2, "0"))).
agg(max("inv_date").alias("max_date"))
在这里,您为所有组生成最新日期(由分组键定义为年份和月份,格式为yyyy-MM
"inv_date"
与startDate
不超过36个月{{1} }}