UNION 后跟 DISTINCT
假设记录是唯一的,实现您想要的最简单的方法是使用 UNION 并在其后添加 DISTINCT:
val df1 = Seq((1, "name1", 18), (2, "name2", 20)).toDF("ID", "Name", "age")
val df2 = Seq((1, "name1", 18), (3, "name3", 19)).toDF("ID", "Name", "age")
df1.unionAll(df2).distinct.show
// +---+-----+---+
// | ID| Name|age|
// +---+-----+---+
// | 1|name1| 18|
// | 2|name2| 20|
// | 3|name3| 19|
// +---+-----+---+
特点:
- 只能访问
df1 一次
- 随机播放
df1 和 df2 与大小无关
EXCEPT 后跟 UNION
另一种方法是使用EXCEPT,后跟UNION:
df1.unionAll(df2.except(df1)).show // df2.distinct.except to drop duplicates
// +---+-----+---+
// | ID| Name|age|
// +---+-----+---+
// | 1|name1| 18|
// | 2|name2| 20|
// | 3|name3| 19|
// +---+-----+---+
属性:
- 必须访问
df1 两次
- 随机播放两个帧,与大小无关 (?)
- 可用于三帧 (
df3.unionAll(df2.except(df1)))
LEFT OUTER JOIN 后接 SELECT 过滤器后接 UNION
最后,如果您只想部分匹配 LEFT OUTER JOIN 与过滤器后跟 UNION 应该可以解决问题:
df2.as("df2")
.join(
df1.select("id", "name").as("df1"),
// join on id and name
$"df1.id" === $"df2.id" && $"df1.name" === $"df2.name",
"leftouter")
// This could be replaced by .na.drop(...)
.where($"df1.id".isNull && $"df1.Name".isNull)
.select($"df2.id", $"df2.name", $"df2.age")
.unionAll(df1)
.show
// ---+-----+---+
// | ID| Name|Age|
// +---+-----+---+
// | 3|name3| 19|
// | 1|name1| 18|
// | 2|name2| 20|
// +---+-----+---+
属性:
- 必须访问
df1 两次
- 如果其中一个数据帧小到可以广播,则可能不需要 shuflle
- 可用于三个数据帧