Вы можете использовать full outer join
Позволяет моделировать ваши данные с помощью классов дел:
case class MyClass1(id: String)
case class MyClass2(id: String, value: String)
// this one for the result type
case class MyClass3(id: String, value: Option[String] = None, value2: Option[String] = None)
Создание нескольких входных данных:
val input1: Dataset[MyClass1] = ...
val input2: Dataset[MyClass2] = ...
Объединение ваших данных:
import scala.implicits._
val joined = input1.as("1").joinWith(input2.as("2"), $"1.id" === $"2.id", "full_outer")
joined map {
case (left, null) if left != null => MyClass3(left.id)
case (null, right) if right != null => MyClass3(right.id, Some(right.value))
case (left, right) => MyClass3(left.id, Some(right.value), Some(right.value))
}