Apache spark Spark数据帧中的列值比较

Apache spark Spark数据帧中的列值比较,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,我有一个包含大量记录的数据框。在这种情况下,记录可以重复多次,每次更新时,上次更新的字段都会有记录修改的日期 我们有一组列,希望在这些列上比较相似ID的行。在比较过程中,我们希望捕获哪些字段/列从以前的记录更改为当前记录,并在更新记录的“更新的_列”列中捕获这些字段/列。将第二条记录与第三条记录进行比较,识别更新的列并在第三条记录的“更新的列”字段中捕获,继续相同操作,直到该id的最后一条记录,并对每个具有多个条目的id执行相同操作 最初,我们对列进行分组,并从该组列中创建一个散列,并与下一行的

我有一个包含大量记录的数据框。在这种情况下,记录可以重复多次,每次更新时,上次更新的字段都会有记录修改的日期

我们有一组列,希望在这些列上比较相似ID的行。在比较过程中,我们希望捕获哪些字段/列从以前的记录更改为当前记录,并在更新记录的“更新的_列”列中捕获这些字段/列。将第二条记录与第三条记录进行比较,识别更新的列并在第三条记录的“更新的列”字段中捕获,继续相同操作,直到该id的最后一条记录,并对每个具有多个条目的id执行相同操作

最初,我们对列进行分组,并从该组列中创建一个散列,并与下一行的散列值进行比较,这样可以帮助我识别有更新的记录,但需要更新的列

这里我分享一些数据,这是预期的结果,这就是添加更新列后最终数据的外观(这里我可以说,使用列Col1、Col2、Col3、col4和Col5在两行之间进行比较):

我想以一种有效的方式来做这件事。任何人都试过这样的东西

正在寻求帮助


~Krish.

您可以将数据帧或数据集连接到自身,连接两行中id相同的行,左侧行的版本为
i
,右侧行的版本为
i+1
。这里有一个例子

case class T(id: String, version: Int, data: String)

val data = Seq(T("1", 1, "d1-1"), T("1", 2, "d1-2"), T("2", 1, "d2-1"), T("2", 2, "d2-2"), T("2", 3, "d2-3"), T("3", 1, "d3-1"))
data: Seq[T] = List(T(1,1,d1-1), T(1,2,d1-2), T(2,1,d2-1), T(2,2,d2-2), T(2,3,d2-3), T(3,1,d3-1))

val ds = data.toDS

val joined = ds.as("ds1").join(ds.as("ds2"), $"ds1.id" === $"ds2.id" && (($"ds1.version"+1) === $"ds2.version"))
然后您可以引用新数据框/数据集中的列,如
$”ds1.data
$”ds2.data

要查找数据从一个版本更改为另一个版本的行,可以执行以下操作

joined.filter($"ds1.data" !== $"ds2.data")
A可以使用

其思想是按ID对数据进行分组,按上次更新的数据进行排序,将前一行的值(如果存在)复制到当前行中,然后将复制的数据与当前值进行比较

val数据=//dataframe具有列ID、Col1、Col2、Col3、Col4、Col5、LAST_UPDATED、IS_DELETED
val fieldNames=data.schema.fieldNames.dropRight(1)//1
val columns=fieldNames.map(f=>col(f))
val windowspec=Window.partitionBy(“ID”).orderBy(“上次更新”)//2
def comparararayudf()=//3.
val结果=数据
.withColumn(“cur”,数组(列:*)//4
.withColumn(“prev”,lag($“cur”,1).over(windowspec))//5
.withColumn(“更新的_列”,comparararayudf()($“cur”,“$“prev”))//6
.drop(“cur”、“prev”)//7
.orderBy(“上次更新”)
备注:

  • 创建要比较的所有字段的列表。将使用除最后一个字段(上次更新)之外的所有字段
  • 创建一个按ID分区的窗口,每个分区按上次更新的ID排序
  • 创建一个udf,用于比较两个数组并将发现的差异映射到字段名,代码见下文
  • 创建一个新列,其中包含应比较的所有值
  • 创建一个新列,其中包含应进行比较的前一行的所有值(通过使用-函数)。前一行是具有相同ID且上次更新的最大值小于当前值的行。此字段可以为空
  • 比较两个新列并将结果放入更新的列中
  • 删除在步骤3和4中创建的两个中间列
  • Aysudf的比较结果是

    def compararray(cur:mutable.WrappedArray[String],prev:mutable.WrappedArray[String]):String={
    if(prev==null | | cur==null)返回“”
    val res=新的StringBuilder
    
    对于(我用图形表示总是有帮助的!我用示例更新了问题,谢谢。这是一个自联接,但有了它,我们如何才能知道值从上一个记录更改为当前记录的列的列表?我在这里遗漏了什么吗?我更新了答案,并展示了一个如何比较val的示例将一行的值与另一行的值进行比较。希望这能为您提供一个共享视图的ideaThanks,我已经解决了这个问题,但这需要逐列比较,然后我可以捕获更新的列并填充更新的列。我正在寻找一些比较字段和deri的有效方法更新数据的字段名,然后我可以在更新的列中填充它。即使我们有一个非常类似的用例,但我们的数量非常巨大,当我使用Window.partitionBy(“ID”)时,记录量为1.5亿条,它正在创建太多的分区,并且正在失败。是否有办法绕过此问题,或者我在我的情况下做了一些错误的事情?期待获得帮助!