如何使用列连接数据集作为要加入的键集合?

时间:2018-03-13 19:50:55

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

我试图弄清楚如何连接两个数据帧,其中一个数据帧包含一个列表,该列表具有要加入的键。

例如:

  • 一个数据框的格式为(id: String, ...,...)
  • 另一个人有(... ,..., List[tmpObj])
  • tmpObj的结构如下(id: String, value: int)

我的目标是通过第二个dataFrame的tmpObj列表中的id值将这两个数据帧连接到第一个数据帧的id。

有没有人知道如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

你可以编写一个UDF来检查列表是否包含给定的id:

val df1 = Seq("a","b","c").toDF("id")

case class TmpObject(id:String,value:Int)

val df2 = Seq(
  Seq(
    TmpObject("a",1),
    TmpObject("c",2)
  )
).toDF("list")

val arrayContains = udf((xs:Seq[String],s:String) => xs.contains(s))

df1.join(df2,arrayContains($"list.id",$"id"),"left")
  .show()


+---+--------------+
| id|          list|
+---+--------------+
|  a|[[a,1], [c,2]]|
|  b|          null|
|  c|[[a,1], [c,2]]|
+---+--------------+

答案 1 :(得分:1)

可以使用内置SQL函数array_contains

import org.apache.spark.sql.functions._

df1.join(df2, expr("array_contains(list.id, id)"), "left")

注意:您可能想尝试直接使用org.apache.spark.sql.functions.array_config(不是在expr的调用中,即df1.join(df2, array_contains($"list.id", $"id"), "left")),但是赢了&# 39;在这种情况下,因为它的签名将其用法限制在第二个参数是某个常量值的情况下(期望Any但是如果参数的类型是Column则失败)。 / p>

答案 2 :(得分:1)

explode上使用joinid第一个数据框:

df2.withColumn("obj", explode($"list_obj")).
  join(df1, $"obj.id" === $"id", "right")