Spark实用议题系列(05)--- 比较两个DataFrame的变化,获取相应的增/删/改子DataFrame

本文探讨如何在Spark中比较两个具有相同Schema的DataFrame,以获取增、删、改记录。通过实例展示了考虑时间戳和处理null值的情况,提供了解决这些问题的Spark代码实现。

Table of Contents

两个DataFrame的纯比较

考虑加入和更新时间的DataFrame比较

DataFrame的字段有null值的情况


我们将DataFrame看作是由一行行(Row)的记录组成的。有时我们会比较两个有相同Schema的DataFrame,而获取一个DataFrame相对于另一DataFrame需要增/删/改的记录。也就是说,原始有一个老DataFrame,在经过这些增/删/改的操作后,就能得到参与比较的新DataFrame。当然,在决定改的记录时,一定是规定了这两个DataFrame相同的主键字段。下面分享自己求取这些子DataFrame的方法。

两个DataFrame的纯比较

这里给出这两个DataFrame的例子,和它们的主键:

val oldDF = Seq[(Integer,String,Integer)](
  (1, "zhang", 12),
  (2, "wang", 49),
  (3, "li", 18),
  (4, "luo", 28)
).toDF("Id", "Name", "Age")

val newDF = Seq[(Integer,String,Integer)](
  (2, "wang", 49),
  (3, "li", 61),
  (4, "luo", 28),
  (5, "zhou", 58)
).toDF("Id", "Name", "Age")

val priKeys = Seq("Id")

一般来说,比较两个DataFrame得到的增/删/改三个子DataFrame可看作一组结果。而有时会不区分增加更改记录,这是因为:1)计算更简单;2)有些数据库的Update操作就可以涵盖Insert,例如,DB2就有MERGE的语句统一处理这两种记录。这里将它们称作删除/增改两个子DataFrame。下面是实现的Spark代码:

import org.apache.spark.sql.DataFrame

case class GroupInsUptDel(insDF: DataFrame, uptDF: DataFrame, delDF: DataFrame)
def genInsUptDel(newDF: DataFrame, oldDF: DataFrame, priKeys: Seq[String]): GroupInsUptDel = {

 val oldCL = oldDF.columns
  
 val delDF = oldDF.join(newDF, priKeys, "left_anti")
 val insDF = newDF.join(oldDF, priKeys, "left_anti")
 val uptDF = newDF.join(oldDF, priKeys, "left_semi").select(oldCL.head, oldCL.tail:_*).exceptAll(oldDF)

 GroupInsUptDel(insDF, uptDF, delDF)
}

case class GroupDeltUpsr(deltDF: DataFrame, upsrDF: DataFrame)
def genDeltUpsr(newDF: DataFrame, oldDF: DataFrame, priKeys: Seq[String]): GroupDeltUpsr = {

 val oldCL = oldDF.columns
  
 val deltDF = oldDF.join(newDF, priKeys, "left_anti")
 val upsrDF = newDF.select(oldCL.head, oldCL.tail:_*).exceptAll(oldDF)

 GroupDeltUpsr(deltDF, upsrDF)
}

求取增/删/改三个子DataFrame的例子:

scala> val grpOne = genInsUptDel(newDF, oldDF, priKeys)
grpOne: GroupInsUptDel = GroupInsUptDel([Id: int, Name: string ... 1 more field],[Id: int, Name: string ... 1 more field],[Id: int, Name: string ... 1 more field])

scala> grpOne.insDF.show(false)
+---+----+---+
|Id |Name|Age|
+---+----+---+
|5  |zhou|58 |
+---+----+---+
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值