繁体   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