简体   繁体   English

子查询根中的联接如何影响JPQL或SQL查询的结果集?

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

This may be a JPQL question or a SQL question, but since it came from a reading of a Criteria example in the JPA Spec. 这可能是JPQL问题,也可能是SQL问题,但是由于它来自JPA Spec中的Criteria示例的阅读。 I'm tagging it JPA and Criteria API too. 我也将其标记为JPA和Criteria API。 I think the problem is that I don't understand how SQL correlated subqueries work. 我认为问题是我不了解SQL相关子查询的工作方式。

Let me begin with JPA Spec. 让我从JPA Spec开始 section 6.5.12, Subqueries, Example 4: A Special Case, which says, 第6.5.12节“ 子查询,示例4:特例”中说:

Note that joins involving the derived subquery root do not affect the join conditions of the containing query. 请注意,涉及派生子查询根的联接不会影响包含查询的联接条件。 The following two query definitions thus differ in semantics: 因此,以下两个查询定义在语义上有所不同:

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

and

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

The first of these queries will return orders that are not associated with customers, whereas the second will not. 这些查询中的第一个查询将返回与客户不相关的订单,而第二个查询则不返回。 The corresponding Java Persistence query language queries are the following: 相应的Java Persistence查询语言查询如下:

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

and

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

The second query seems straightforward but the first is difficult to visualize. 第二个查询似乎很简单,但第一个查询很难可视化。

My understanding of a correlated subquery is that it depends on the outer query; 我对相关子查询的理解是,它取决于外部查询。 it uses the data of the outer query. 它使用外部查询的数据。 It is not independent of the outer query. 它不独立于外部查询。 It executes once for each selected row from the outer query. 它为外部查询中的每个选定行执行一次。

In both queries Orders are being selected in the outer query. 在两个查询中,都在外部查询中选择了订单。 In the first query, for each selected Order from the outer query the following subquery is run: 在第一个查询中,对于从外部查询中选择的每个订单,运行以下子查询:

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

Intuition tells me that the customer associated with the Order record is joined with account. 直觉告诉我与订单记录关联的客户已与帐户一起加入。 Hence the subquery will return the balances of all accounts associated with the particular customer who is associated with the current Order record. 因此,子查询将返回与与当前订单记录关联的特定客户关联的所有帐户的余额。

Am I right or wrong? 我是对还是错? It seems I'm wrong, according to the above example, which, again, says, 根据上述示例,看来我错了,再说一遍,

"Note that joins involving the derived subquery root do not affect the join conditions of the containing query," and, "The first of these queries will return Orders that are not associated with customers..." "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..."

So the subquery does not return account balances of the customer associated with the Order? 因此,子查询不会返回与订单相关联的客户的帐户余额吗? What account balances are instead returned? 而是返回哪些帐户余额? What's the right way to see this? 看这个的正确方法是什么? My head is spinning. 我的头在旋转。

First Query: 第一个查询:

SELECT o
FROM Order o
WHERE 10000 < ALL (
    SELECT a.balance
    FROM o.customer c JOIN c.accounts a)
  1. The outer query is run first. 首先运行外部查询。 The outer query selects all orders, including orders that are not associated with a customer (eg orders fulfilled where buyer chose not to register as a customer). 外部查询选择所有订单,包括与客户不相关的订单(例如,在买家选择不注册为客户的情况下已履行的订单)。
  2. Next, the subquery is run for each record selected in the outer query. 接下来,为外部查询中选择的每个记录运行子查询。

    • If the order has a customer, the subquery returns the balances of all accounts associated with the customer. 如果订单有一个客户,则子查询将返回与该客户关联的所有帐户的余额。 If all balances are < 10000 the ALL condition evaluates to TRUE and the row of the outer query is included in the result set. 如果所有余额均<10000,则ALL条件的值为TRUE,并且外部查询的行包含在结果集中。

    • If a subquery returns zero rows (which would happen in this example if if there is no customer associated with the order) the ALL condition evaluates to TRUE and the row is included in the result. 如果子查询返回零行(如果没有与订单关联的客户,则在本示例中会发生),ALL条件的计算结果为TRUE,并且该行包括在结果中。

The orders in the first query are not associated with customers and therefore the result set will include both orders that have customers and orders that were processed for people who decided not to register as customers. 第一个查询中的订单未与客户相关联,因此结果集将同时包含具有客户的订单和为决定不注册为客户的人处理的订单。

Second Query: 第二个查询:

SELECT o
    FROM Order o JOIN o.customer c
    WHERE 10000 < ALL (
        SELECT a.balance
        FROM c.accounts a)
  1. The outer query is run first. 首先运行外部查询。 The outer query selects only orders that are associated with customers. 外部查询仅选择与客户关联的订单。

  2. Next, the subquery is run for each row. 接下来,为每行运行子查询。

    • If the customer associated with the order has one or more accounts and all of the account balances are< 10000 the ALL condition will evaluate to true and the row in the outer query is included in the result set. 如果与该订单关联的客户有一个或多个帐户,并且所有帐户余额均小于10000,则ALL条件将评估为true,并且外部查询中的行将包含在结果集中。

    • If the customer associated with the order has no accounts the subquery returns zero rows the ALL condition evaluates to true and the row in the outer query is included in the result set. 如果与订单关联的客户没有帐户,则子查询返回零行,则ALL条件的结果为true,并且外部查询中的行包含在结果集中。

The orders in the second query are associated with customers and therefore the result set will not include orders that were processed for people who decided not to register as customers. 第二个查询中的订单与客户相关联,因此结果集将不包含为那些决定不注册为客户的人处理的订单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM