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

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

这可能是 JPQL 问题或 SQL 问题,但因为它来自阅读 JPA 规范中的 Criteria 示例。我也将其标记为 JPA 和 Criteria API。我认为问题是我不明白 SQL 相关子查询是如何工作的。

让我从 JPA Spec. section 6.5.12, Subqueries, Example 4: A Special Case, 开始说,

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:

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)

第二个查询看起来很简单,但第一个查询很难形象化。

我对相关子查询的理解是它依赖于外部查询;它使用外部查询的数据。它不独立于外部查询。它对外部查询中的每个选定行执行一次。

在两个查询中,都在外部查询中选择了订单。在第一个查询中,对于从外部查询中选择的每个订单,以下子查询是 运行:

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

直觉告诉我,与订单记录关联的客户与帐户关联。因此,子查询将 return 与与当前订单记录关联的特定客户关联的所有帐户的余额。

我是对还是错?看来我错了,根据上面的例子,再次说,

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

那么子查询不会return 与订单关联的客户的账户余额? return 是什么账户余额?看到这个的正确方法是什么?我的头在旋转。

第一次查询:

SELECT o
FROM Order o
WHERE 10000 < ALL (
    SELECT a.balance
    FROM o.customer c JOIN c.accounts a)
  1. 外部查询首先是运行。外部查询选择所有订单,包括与客户无关的订单(例如,买家选择不注册为客户的已履行订单)。
  2. 接下来,子查询是运行外层查询中选择的每条记录。

    • 如果订单有客户,则子查询returns与客户关联的所有账户的余额。如果所有余额都小于 10000,则 ALL 条件的计算结果为 TRUE,并且外部查询的行包含在结果集中。

    • 如果子查询 returns 零行(如果没有与订单关联的客户,则在本例中会发生这种情况)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 条件将评估为真,并且外部查询中的行包含在结果中设置.

    • 如果与订单关联的客户没有帐户,则子查询 returns 零行 ALL 条件计算结果为真,并且外部查询中的行包含在结果集中。

第二个查询中的订单与客户相关联,因此结果集将不包括为决定不注册为客户的人处理的订单。