Spark Scala - 识别多行日期之间的差距

Posted

技术标签:

【中文标题】Spark Scala - 识别多行日期之间的差距【英文标题】:Spark Scala - Identify the gap between dates across multiple rows 【发布时间】:2020-01-17 20:54:40 【问题描述】:

我是 Apache Spark 的新手,我有一个用例来查找多个日期之间的日期间隔标识。

例如

在上面的示例中,成员在 2018-02-01 到 2018-02-14 之间存在间隔。如何使用 Scala 找到这个 Apache Spark 2.3.4。

上述场景的例外输出是,

【问题讨论】:

【参考方案1】:

您可以使用datediff 和窗口函数lag 来检查当前行和之前行之间的日期间隔,并使用一些日期函数计算缺失的日期范围:

import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
import spark.implicits._
import java.sql.Date

val df = Seq(
  (1, Date.valueOf("2018-01-01"), Date.valueOf("2018-01-31")),
  (1, Date.valueOf("2018-02-16"), Date.valueOf("2018-02-28")),
  (1, Date.valueOf("2018-03-01"), Date.valueOf("2018-03-31")),
  (2, Date.valueOf("2018-07-01"), Date.valueOf("2018-07-31")),
  (2, Date.valueOf("2018-08-16"), Date.valueOf("2018-08-31"))
).toDF("MemberId", "StartDate", "EndDate")

val win = Window.partitionBy("MemberId").orderBy("StartDate", "EndDate")

df.
  withColumn("PrevEndDate", coalesce(lag($"EndDate", 1).over(win), date_sub($"StartDate", 1))).
  withColumn("DayGap", datediff($"StartDate", $"PrevEndDate")).
  where($"DayGap" > 1).
  select($"MemberId", date_add($"PrevEndDate", 1).as("StartDateGap"), date_sub($"StartDate", 1).as("EndDateGap")).
  show
// +--------+------------+----------+
// |MemberId|StartDateGap|EndDateGap|
// +--------+------------+----------+
// |       1|  2018-02-01|2018-02-15|
// |       2|  2018-08-01|2018-08-15|
// +--------+------------+----------+

【讨论】:

这个很好,但在某些日期重叠的情况下它会失败,例如如果您将 (2, Date.valueOf("2018-05-01"), Date.valueOf("2018-08-05") 添加到 DF,您仍然会得到与上面相同的结果。假设已采取措施删除冗余数据,这仍然是一个很好的答案。 谢谢,但是当日期重叠时它会失败,例如如果你添加 (1,Date.valueOf("2018-01-15"),Date.valueOf("2018-01-30") ) 到 DF,您将获得 StartDateGap 为“2018-01-31”,但该成员的注册日期为“2018-01-31”。您能告诉我如何在计算之前删除重叠天数吗? Leo,我找到了您删除重叠日期的答案之一 (***.com/questions/52877237/…)。非常感谢。我会尽力将这两者合并。如果我需要更多帮助,我会告诉你。非常感谢。 @Gowri24,是的,上述解决方案基于您的简单示例数据,没有重叠日期范围。将我的其他解决方案与此解决方案相结合将起作用。应用其他解决方案后,只需将 win3 定义为 Window.partitionBy("MemberId", "StartDate", "EndDate").orderBy("StartDate", "EndDate") 应用到生成的 DataFrame resDF.withColumn("RowNum", row_number.over(win3)).where($"RowNum" === 1),然后应用上述转换来查找差距。 @LeoC,感谢您的回复。

以上是关于Spark Scala - 识别多行日期之间的差距的主要内容,如果未能解决你的问题,请参考以下文章

如何合并来自多行的值,以便它们可以一起处理 - Spark scala

Spark - Scala:当 json 数据分布在多行时,读取 json 文件作为数据帧不起作用?

如何在 Spark Scala 中读取带有根元素的多行 json?

Spark Scala:在使用 spark 按不同日期排序后,需要获取具有 NULL 日期的记录

在 Spark scala 程序中解析日期时出错 [重复]

Scala - 如何在 Spark SQL 查询中将日期字符串转换为时间戳?