根据两个列值(排除重复项)合并两个spark数据集

时间:2018-07-08 15:59:33

标签: scala apache-spark apache-spark-dataset

我有两个数据集,

Dataset1
+---+------+------+
|cid|itemId|bought|
+---+------+------+
|abc|   123|  true|
|abc|   345|  true|
|abc|   567|  true|
|def|   123|  true|
|def|   345|  true|
|def|   567|  true|
+---+------+------+

Dataset2
+---+------+------+
|cid|itemId|bought|
+---+------+------+
|abc|   123| false|
|abc|   345| false|
|def|   789| false|
+---+------+------+

我的目标是根据以下条件合并这两个数据集。

CID和ItemId组成一个组合(组密钥)。数据集2将检查数据集1中是否存在组键,而合并这些记录时将删除组键,而与第三列中的值无关。

例如,在上面的示例中,数据集2的第一行和第二行将被删除,并且仅第三列将被合并。

所需的输出数据集

+---+------+------+
|cid|itemId|bought|
+---+------+------+
|abc|   123|  true|
|abc|   345|  true|
|abc|   567|  true|
|def|   123|  true|
|def|   345|  true|
|def|   567|  true|
|def|   789| false|
+---+------+------+

这是我正在尝试的逻辑,

根据cid和itemid值对数据集2进行过滤,并在数据集1上进行交集,并将其存储为tempDataset。但是我无法获得可以那样工作的过滤器。仍在寻找它。

在tempDataset和dataset1上应用并集并创建dataset3。

我想知道有没有更简单的方法?

还要如何进行过滤以获取tempDataset?

1 个答案:

答案 0 :(得分:3)

一种方法是先执行left_anti join然后执行union,如下所示:

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

val df1 = Seq(
  ("abc", 123, true),
  ("abc", 345, true),
  ("abc", 567, true),
  ("def", 123, true),
  ("def", 345, true),
  ("def", 567, true)
).toDF("cid", "itemId", "bought")

val df2 = Seq(
  ("abc", 123, false),
  ("abc", 345, false),
  ("def", 789, false)
).toDF("cid", "itemId", "bought")

df1.union( df2.join(df1, Seq("cid", "itemId"), "left_anti") ).
  show
// +---+------+------+
// |cid|itemId|bought|
// +---+------+------+
// |abc|   123|  true|
// |abc|   345|  true|
// |abc|   567|  true|
// |def|   123|  true|
// |def|   345|  true|
// |def|   567|  true|
// |def|   789| false|
// +---+------+------+