Spark SQL Dataframe API - 动态过滤条件动态

时间:2017-12-03 11:45:28

标签: scala apache-spark apache-spark-sql

我有两个Spark数据帧,df1df2

+-------+-----+---+
|   name|empNo|age|
+-------+-----+---+
|shankar|12121| 28|
| ramesh| 1212| 29|
| suresh| 1111| 30|
| aarush| 0707| 15|
+-------+-----+---+
+------+-----+---+-----+
| eName|  eNo|age| city|
+------+-----+---+-----+
|aarush|12121| 15|malmo|
|ramesh| 1212| 29|malmo|
+------+-----+---+-----+

我需要根据另一个文件中指定的列数,从df1获取非匹配记录

例如,列查找文件如下所示:

df1col,df2col
name,eName
empNo, eNo

预期输出为:

+-------+-----+---+
|   name|empNo|age|
+-------+-----+---+
|shankar|12121| 28|
| suresh| 1111| 30|
| aarush| 0707| 15|
+-------+-----+---+

这个想法是如何为上述场景动态构建where条件,因为查找文件是可配置的,因此它可能有1到n个字段。

2 个答案:

答案 0 :(得分:3)

您可以使用except数据框方法。为了简单起见,我假设要使用的列在两个列表中。必须使两个列表的顺序正确,将比较列表中相同位置的列(无论列名称如何)。在except之后,使用join从第一个数据框中获取缺少的列。

val df1 = Seq(("shankar","12121",28),("ramesh","1212",29),("suresh","1111",30),("aarush","0707",15))
  .toDF("name", "empNo", "age")
val df2 = Seq(("aarush", "12121", 15, "malmo"),("ramesh", "1212", 29, "malmo"))
  .toDF("eName", "eNo", "age", "city")

val df1Cols = List("name", "empNo")
val df2Cols = List("eName", "eNo")

val tempDf = df1.select(df1Cols.head, df1Cols.tail: _*)
  .except(df2.select(df2Cols.head, df2Cols.tail: _*))    
val df = df1.join(broadcast(tempDf), df1Cols)

结果数据框看起来像是想要的:

+-------+-----+---+
|   name|empNo|age|
+-------+-----+---+
| aarush| 0707| 15|
| suresh| 1111| 30|
|shankar|12121| 28|
+-------+-----+---+

答案 1 :(得分:0)

如果您是从SQL查询执行此操作,我将使用Changing a SQL column title via query之类的内容重新映射SQL查询本身中的列名。您可以在查询中执行简单的文本替换,以将它们规范化为df1或df2列名称。

一旦你有了这个,你就可以使用像 How to obtain the difference between two DataFrames?

如果您需要更多不在diff中使用的列(例如age),您可以根据diff结果重新选择数据。这可能不是最佳方式,但可能会有效。