2016-10-02 3 views
0

これはJPQL質問またはSQL質問かもしれませんが、それはJPA仕様のCriteriaの例を読んだことに由来しています。 JPAとCriteria APIもタグ付けしています。問題は、SQLの相関サブクエリの仕組みがわからないことだと思います。 サブクエリ・ルートの結合は、JPQLまたはSQL問合せの結果セットにどのように影響しますか?

は を含むクエリの結合条件は影響しません派生サブクエリのルートを含むジョイン

注、私は言うJPA Spec. section 6.5.12, Subqueries, Example 4: A Special Case,から始めましょう。次の二つのクエリ 定義ので、セマンティクスが異なる:

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 永続クエリ言語クエリは、次のとおりです。

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) 

2番目のクエリは、簡単なようだが、最初は視覚化することは困難です。

相関サブクエリについての理解は、外側のクエリに依存することです。外部クエリのデータを使用します。外部クエリとは独立していません。外部クエリから選択された行ごとに1回実行されます。

両方のクエリで、外部クエリで注文が選択されています。最初のクエリでは、外部クエリから選択した各注文については、以下のサブクエリが実行されます:

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

直感が受注レコードに関連付けられている顧客が口座に参加していることを私に伝えます。したがって、サブクエリは、現在のOrderレコードに関連付けられている特定の顧客に関連付けられたすべてのアカウントの残高を返します。

私は間違っていますか?とてもサブクエリが注文に関連付けられた顧客の口座残高を返さない?これ、再び、と言い、

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

、上記の例によると、私が間違っているようですかその代わりにどの勘定残高が返されますか?これを見て正しい方法は何ですか?私の頭がクラクラします。

+0

あなたの 'join'は' on'節を持たないので、そのクエリに従うのは難しいです。 –

+0

JPA 2.1仕様からまっすぐに出てくる例であるため、クエリを変更したくありません。 –

答えて

0

最初のクエリ:外側のクエリが最初に実行される

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と評価され、結果に行が含まれます。最初のクエリで

受注が顧客に関連付けられていないため、結果セットは、顧客として登録しないことを決定した人のために処理した顧客と注文を持っている両方の注文が含まれます。

2番目のクエリ:外側のクエリが最初に実行される

SELECT o 
    FROM Order o JOIN o.customer c 
    WHERE 10000 < ALL (
     SELECT a.balance 
     FROM c.accounts a) 
  1. 。外部クエリは、顧客に関連付けられた注文のみを選択します。

  2. 次に、各行に対してサブクエリが実行されます。

    • ために関連付けられている顧客は、1つのまたは複数のアカウントを持っており、口座残高のすべてが、すべての条件が真と評価され、外側のクエリ内の行が結果セットに含まれている< 10000ある場合。

    • 注文に関連付けられた顧客にアカウントがない場合、サブクエリはゼロ行を返します。ALL条件はtrueと評価され、外部クエリの行は結果セットに含まれます。

2番目のクエリでの受注は、顧客に関連付けられているため、結果セットは、顧客として登録しないことを決定した人のために処理した受注は含まれません。

関連する問題