簡體   English   中英

子查詢根中的聯接如何影響JPQL或SQL查詢的結果集?

[英]How do joins in subquery root affect the result set of a JPQL or SQL query?

這可能是JPQL問題,也可能是SQL問題,但是由於它來自JPA Spec中的Criteria示例的閱讀。 我也將其標記為JPA和Criteria API。 我認為問題是我不了解SQL相關子查詢的工作方式。

讓我從JPA Spec開始 第6.5.12節“ 子查詢,示例4:特例”中說:

請注意,涉及派生子查詢根的聯接不會影響包含查詢的聯接條件。 因此,以下兩個查詢定義在語義上有所不同:

CriteriaQuery<Order> q = cb.createQuery(Order.class);
Root<Order> order = q.from(Order.class);
Subquery<Integer> sq = q.subquery(Integer.class);
Root<Order> orderSub = sq.correlate(order);
Join<Order,Customer> customer = orderSub.join(Order_.customer);
Join<Customer,Account> account = customer.join(Customer_.accounts);
sq.select(account.get(Account_.balance));
q.where(cb.lt(cb.literal(10000), cb.all(sq)));

CriteriaQuery<Order> q = cb.createQuery(Order.class);
Root<Order> order = q.from(Order.class);
Join<Order,Customer> customer = order.join(Order_.customer);
Subquery<Integer> sq = q.subquery(Integer.class);
Join<Order,Customer> customerSub = sq.correlate(customer);
Join<Customer,Account> account = customerSub.join(Customer_.accounts);
sq.select(account.get(Account_.balance));
q.where(cb.lt(cb.literal(10000), cb.all(sq)));

這些查詢中的第一個查詢將返回與客戶不相關的訂單,而第二個查詢則不返回。 相應的Java Persistence查詢語言查詢如下:

SELECT o
FROM Order o
WHERE 10000 < ALL (
    SELECT a.balance
    FROM o.customer c JOIN c.accounts a)

SELECT o
FROM Order o JOIN o.customer c
WHERE 10000 < ALL (
    SELECT a.balance
    FROM c.accounts a)

第二個查詢似乎很簡單,但第一個查詢很難可視化。

我對相關子查詢的理解是,它取決於外部查詢。 它使用外部查詢的數據。 它不獨立於外部查詢。 它為外部查詢中的每個選定行執行一次。

在兩個查詢中,都在外部查詢中選擇了訂單。 在第一個查詢中,對於從外部查詢中選擇的每個訂單,運行以下子查詢:

SELECT a.balance FROM o.customer c JOIN c.accounts a

直覺告訴我與訂單記錄關聯的客戶已與帳戶一起加入。 因此,子查詢將返回與與當前訂單記錄關聯的特定客戶關聯的所有帳戶的余額。

我是對還是錯? 根據上述示例,看來我錯了,再說一遍,

"Note that joins involving the derived subquery root do not affect the join conditions of the containing query,""The first of these queries will return Orders that are not associated with customers..."

因此,子查詢不會返回與訂單相關聯的客戶的帳戶余額嗎? 而是返回哪些帳戶余額? 看這個的正確方法是什么? 我的頭在旋轉。

第一個查詢:

SELECT o
FROM Order o
WHERE 10000 < ALL (
    SELECT a.balance
    FROM o.customer c JOIN c.accounts a)
  1. 首先運行外部查詢。 外部查詢選擇所有訂單,包括與客戶不相關的訂單(例如,在買家選擇不注冊為客戶的情況下已履行的訂單)。
  2. 接下來,為外部查詢中選擇的每個記錄運行子查詢。

    • 如果訂單有一個客戶,則子查詢將返回與該客戶關聯的所有帳戶的余額。 如果所有余額均<10000,則ALL條件的值為TRUE,並且外部查詢的行包含在結果集中。

    • 如果子查詢返回零行(如果沒有與訂單關聯的客戶,則在本示例中會發生),ALL條件的計算結果為TRUE,並且該行包括在結果中。

第一個查詢中的訂單未與客戶相關聯,因此結果集將同時包含具有客戶的訂單和為決定不注冊為客戶的人處理的訂單。

第二個查詢:

SELECT o
    FROM Order o JOIN o.customer c
    WHERE 10000 < ALL (
        SELECT a.balance
        FROM c.accounts a)
  1. 首先運行外部查詢。 外部查詢僅選擇與客戶關聯的訂單。

  2. 接下來,為每行運行子查詢。

    • 如果與該訂單關聯的客戶有一個或多個帳戶,並且所有帳戶余額均小於10000,則ALL條件將評估為true,並且外部查詢中的行將包含在結果集中。

    • 如果與訂單關聯的客戶沒有帳戶,則子查詢返回零行,則ALL條件的結果為true,並且外部查詢中的行包含在結果集中。

第二個查詢中的訂單與客戶相關聯,因此結果集將不包含為那些決定不注冊為客戶的人處理的訂單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM