2016-01-18 61 views
6

我試圖運行使用EXIST子句的查詢:星火替代EXISTS和IN

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>) 

不幸的是,這似乎並沒有得到支持。我也曾嘗試與IN條款替換EXISTS條款:

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 ...) 

不幸的是,還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 

溶液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 
+0

您的第一個查詢模板不應該是EXIST調用形式存在(選擇E.ID從 E其中E.ID = A.ID))? – philipxy

回答

13

SparkSQL目前沒有EXISTS & IN。 "(Latest) Spark SQL/DataFrames and Datasets Guide/Supported Hive Features"

EXISTS & IN始終可以使用JOIN或LEFT SEMI JOIN重寫。 OR總是可以使用UNION重寫。不能用EXCEPT重寫。

表持有,使一些謂詞真(聲明列名參數)行:

  • 的DBA給出了每個基表的謂詞T與列T.C,...ŧTC,...)
  • A JOIN包含使其AND的理由ts'謂詞正確;對於UNION,OR;對於EXCEPT,AND NOT。
  • SELECT DISTINCTkept columnsFROMT成立,其中EXISTS 丟棄列 [謂詞Ť的]的行。
  • TLEFT SEMI JOINU成立,其中EXISTS U形僅列 [T的謂詞與謂詞Ù的]的行。
  • TWHEREcondition保持行其中T謂詞與條件

(重新查詢通常看到this answer。)

因此,通過記住謂詞表達式保持相應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 

您的解決方案1不會做你認爲它的工作。如果exists_clause表中只有一個爲空,即即使有另一個可用的ID匹配,表的FROM交叉乘積也是空的,並且不返回任何行。 ("An Unintuitive Consequence of SQL Semantics": Chapter 6 The Database Language SQL sidebar page 264 of Database Systems: The Complete Book 2nd Edition.) FROM不只是引入錶行的名稱,它是CROSS JOINing和/或OUTER JOINing它們之後ON(對於INNER JOIN)和WHERE過濾出一些表。

對於返回相同行的不同表達式,性能通常不同。這取決於DBMS優化。 DBMS和/或程序員可能知道的許多細節,如果可能,可能會或可能不知道,並且可能或可能不會達到最佳平衡,這會影響評估查詢的最佳方式以及編寫查詢的最佳方式。但是在WHERE中每行執行兩個ORed子查詢(就像在你原來的查詢中一樣,但也是你晚期的解決方案2)並不一定比運行兩個SELECT中的一個UNION更好(就像在我的查詢中那樣)。

+0

謝謝你的回覆!我最終爲每個select語句使用子查詢,並在所有基本關係和子查詢計算的關係之間執行一個巨大的連接。我認爲你的解決方案有些不同,儘管我沒有完全理解它。你可以勾畫一個查詢模板更精確嗎? (我正在編輯問題以添加我當前的解決方案) – Radu

+0

另外,您提到性能通常會有所不同。你能否提供一個暗示爲什麼會這樣? – Radu

+0

我已更新我的答案以解決您的意見。重新性能,您應該閱讀關於關係查詢優化,這實際上意味着關係查詢實現。有許多在線通用和特定產品的書籍,谷歌的SQL性能等。 – philipxy