Spark替换EXISTS和IN

Rad*_*adu 10 sql apache-spark-sql

我试图运行使用EXIST子句的查询:

select <...>    
  from A, B, C
where
  A.FK_1 = B.PK and
  A.FK_2 = C.PK and
  exists (select A.ID from <subquery 1>) or 
  exists (select A.ID from <subquery 2>) 
Run Code Online (Sandbox Code Playgroud)

不幸的是,这似乎不受支持.我也尝试用EXISTS一个IN子句替换该子句:

select <...>    
  from A, B, C
where
  A.FK_1 = B.PK and
  A.FK_2 = C.PK and
  A.ID in (select ID from ...) or
  A.ID in (select ID from ...)
Run Code Online (Sandbox Code Playgroud)

不幸的是,该IN条款似乎也没有得到支持.

有关如何编写实现所需结果的SQL查询的任何想法?我原则上可以将该WHERE条款建模为另一个条款,JOIN而第二个OR条款则可以模拟,UNION但它看起来非常笨拙.

编辑:列出一些可能的解决方案.

解决方案1

select <...>    
  from A, B, C
       (select ID from ...) as exist_clause_1,
       (select ID from ...) as exist_clause_2,
where
  A.FK_1 = B.PK and
  A.FK_2 = C.PK and
  A.ID = exist_clause_1.ID or
  A.ID = exist_clause_2.ID
Run Code Online (Sandbox Code Playgroud)

解决方案2

select <...>    
  from A, B, C
       ( (select ID from ...) UNION
         (select ID from ...)
        ) as exist_clause,
where
  A.FK_1 = B.PK and
  A.FK_2 = C.PK and
  A.ID = exist_clause.ID
Run Code Online (Sandbox Code Playgroud)

phi*_*pxy 16

SparkSQL目前没有EXISTS&IN."(最新)Spark SQL/DataFrames和数据集指南/支持的Hive功能"

始终可以使用JOIN或LEFT SEMI JOIN重写EXISTS&IN."尽管Apache Spark SQL目前不支持IN或EXISTS子查询,但您可以通过重写查询以使用LEFT SEMI JOIN来有效地实现语义." OR总是可以使用UNION重写.AND NOT可以使用EXCEPT重写.

表保存使某些谓词(由列名参数化的语句)为true的行:

  • DBA为每个基表T提供带有列的谓词T.C,...:T(TC,...)
  • A JOIN保存使其参数的AND'谓词为真的行; 对于a UNION,OR; 为了EXCEPT,AND NOT.
  • SELECT DISTINCTkept columnsFROMT保存EXISTS 删除列的行[ T的谓词 ].
  • TLEFT SEMI JOINU保持EXISTS U-only列的行[ U 的T的谓词谓词 ].
  • TWHEREcondition保存T AND 条件谓词的行.

(重新查询一般会看到这个答案.)

因此,通过记住与SQL对应的谓词表达式,您可以使用直接的逻辑重写规则来组合和/或重新组织查询.例如,在可读性或执行方面,使用UNION不需要"笨拙".

您的原始问题表明您了解可以使用UNION,并且您已在您的问题中编辑了变体,从原始查询中删除了EXISTS和IN.这是另一个变体也切除OR.

    select <...>    
    from A, B, C, (select ID from ...) as e
    where
      A.FK_1 = B.PK and
      A.FK_2 = C.PK and
      A.ID = e.id
union
    select <...>    
    from A, B, C, (select ID from ...) as e
    where
      A.FK_1 = B.PK and
      A.FK_2 = C.PK and
      A.ID = e.ID
Run Code Online (Sandbox Code Playgroud)

您的解决方案1没有按照您的想法执行.如果只有一个exists_clause表是空的,即即使另一个表中有ID可用的匹配项,表的FROM交叉产品也是空的,并且不返回任何行.("SQL语义的一个不直观的后果":第6章数据库系统的数据库语言SQL侧栏第264页:完整的第2版.) FROM不只是引入表行的名称,它是CROSS JOINING和/或OUTER加入它们之后ON(对于INNER JOINs)和WHERE过滤掉一些.

对于返回相同行的不同表达式,性能通常是不同的.这取决于DBMS优化.DBMS和/或程序员可能知道的许多细节,如果可能知道或可能不知道,可能或可能不能达到最佳平衡,会影响评估查询的最佳方式以及编写查询的最佳方式.但是在WHERE中每行执行两个ORed子选择(如在原始查询中,但也在您的已解决的解决方案2中)并不一定比运行两个SELECT的UNION更好(如在我的查询中).