Apache spark 如何使用或约束多个半连接?

Apache spark 如何使用或约束多个半连接?,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,如何在SparkSQL或Dataframe API中使用semijoin实现下面的SQL select * from foo left join a on foo.id = a.id left join b on foo.id = b.id where exists (select 1 from a x where foo.id = x.id) or exists (select 1 from b x where foo.id = x.id) ; 我已经试过了,但它的功能是和 .join(l

如何在SparkSQL或Dataframe API中使用semijoin实现下面的SQL

select * 
from foo
left join a on foo.id = a.id
left join b on foo.id = b.id
where exists (select 1 from a x where foo.id = x.id)
or exists (select 1 from b x where foo.id = x.id)
;
我已经试过了,但它的功能是和

.join(loincDF, foo("id") <=> a("id"), "leftsemi")
.join(loincDF, foo("id") <=> b("id"), "leftsemi")

您可以尝试以下方法:

foo.join(a, Seq("id"), "leftsemi")
   .union( foo.join(b, Seq("id"), "leftsemi") )
   .distinct

正如@Elmar Macek的解决方案所指出的,左_半连接的并集模仿exists子句的OR条件。但是,left_-semi-join不会从右侧数据帧生成相应的列。要生成与包含左联接的SQL等价的结果,可以在应用模拟exists函数的过滤逻辑之前先执行左外部联接

以下是几种方法:

方法1:执行左_外部联接,然后执行左_半联接

val foo=Seq 1,f1,2,f2,3,f3,4,f4,5,f5 .toDFid,姓名 val a=序列号 1、a1、3、a3 .托德菲德,描述 val b=序列号 1、b1、4、b4 .托德菲德,描述 val bar=foo。 joina,Seqid,左外。 joinb,Seqid,左外 bar.joina,序号,左半。 协会 条形接头B,序号,左半 . 不同的 显示 // +--+--+--+--+ //| id | name | desc | desc| // +--+--+--+--+ //| 4 | f4 |空| b4| //| 1 | f1 | a1 | b1| //| 3 | f3 | a3 |空| // +--+--+--+--+ 方法2:执行left_外部联接,然后对非键列执行null检查

val aNonKeyCols=a.columns.filter!身份证件 val a2=a.WithColumnCols,structaNonKeyCols.mapcols:*。 选择ID,aCols val bNonKeyCols=b.columns.filter\u1!=身份证件 val b2=b.withColumnbCols,structaNonKeyCols.mapcol:*。 selectid,bCols val bar=foo。 接头2,序号,左外。 接头2,Seqid,左外。 其中$aCols.isNotNull | |$bCols.isNotNull。 selectid、name、aCols.*、bCols*
请注意,假设可能有许多列,a和b的非键列都放在一个结构中,以简化空检查。

有没有办法在不使用不同字符的情况下执行此操作?我有相当多的列和大量的行,你可以这样做:你可以做两个leftouter连接,然后检查以这种方式添加到foo的a或b的列中是否至少有一个存在。所以在leftouter连接之后,你基本上会过滤那些存在a.X或b.Y的行。有没有什么方法可以在没有明显差异的情况下做到这一点?我有相当多的专栏和很多文章rows@Josh,请参阅我的扩展答案,其中包括另一种方法。