13

我试图通过加入子查询来获得 groupBy 计数的平均值。不知道这是否是正确的方法,但除了 mysema 文档之外,我对子查询一无所知。

场景:客户平均每个产品做了多少订单?含义:客户订购产品。因此,客户多次(计数)订购了特定产品。客户为任何产品下的平均订单数是多少?

可能听起来有点假设,实际上它只是原型的一部分,但它让我想知道,如何使用来自 Mysema 的奇特 QueryDSL 获取对在子查询中创建的自定义列的引用。

在 SQL 中,您只需给计数列一个别名并使用第二个 ID 列连接。QueryDSL 也有“as()”方法,但我不知道如何检索该列,而且我不知道它如何将一个查询与另一个查询连接起来,因为 query.list() 只是获取一个列表,但对于某些加入接受它的原因。感觉不对...

这是我的代码:

    JPQLQuery query = createJPQLQuery();

    QOrdering qOrdering = QOrdering.ordering;
    QProduct qProduct = QProduct.product;
    QCustomer qCustomer = QCustomer.customer;           

    // how many of each product did a customer order?
    HibernateSubQuery subQuery = new HibernateSubQuery();
    subQuery.from(qOrdering).innerJoin(qOrdering.product,qProduct).innerJoin(qOrdering.customer, qCustomer);
    subQuery.groupBy(qCustomer,qProduct).list(qCustomer.id,qProduct.id,qProduct.count());

    // get the average number of orders per product for each customer
    query.from(qCustomer);      
    query.innerJoin(subQuery.list(qCustomer.id,qOrdering.count().as("count_orders")));      
    query.groupBy(qCustomer.id);
    return (List<Object[]>) query.list(qCustomer.firstname,subQuery.count_orders.avg());

再次:我如何加入子查询?我如何获得别名“count”列以进行更多聚合,如 avg(顺便说一句,我的组对吗?)可能是我在这方面有一些其他错误,所以任何帮助表示赞赏!

谢谢!

编辑: 这是我希望 QueryDSL 产生的原生 SQL:

Select avg(numOrders) as average, cust.lastname from
customer cust
inner join
(select count(o.product_id) as numOrders, c.id as cid, p.name
from ordering o
inner join product p on o.product_id=p.id
inner join customer c on o.customer_id=c.id
group by o.customer_id, o.product_id) as numprods
on cust.id = numprods.cid
group by numprods.cid
order by cust.lastname;
4

3 回答 3

19

不允许在连接子句中使用子查询。在 JPQL 中,子查询只允许在 WHERE 和 HAVING 部分。Querydsl JPA 查询中的连接方法签名太宽。

由于该查询需要两级分组,可能无法用JPQL / Querydsl JPA 表示。

我建议使用 Querydsl JPA Native 查询支持来编写这个查询。

由于 Querydsl JPA 在内部使用 JPQL,因此受限于 JPQL 的表现力。

于 2011-08-05T06:07:30.433 回答
1

我知道这个问题很老,并且已经有一个公认的答案,但是从这个问题来看,它似乎仍然令人不安。在同一个问题中查看我的答案。JoinFlagjoin()section中的使用Expression.path()是能够实现子查询的左连接。希望这可以帮助某人。

于 2019-04-10T07:16:36.973 回答
1

QueryDsl 不支持连接中的子查询,但您可以通过以下方式实现:

我们想要实现以下查询:

select A.* from A join (select aid from B group by aid) b on b.aid=A.id;

将视图或 SQL 查询映射到 JPA 实体:

import lombok.Setter;
import org.hibernate.annotations.Subselect;
import org.hibernate.annotations.Synchronize;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
@Getter
@Setter
@Subselect("select aid from B group by aid")
@Synchronize("B")
public class BGroupByAid {

    @Id
    private Integer aId;
}

然后在类中使用等效的 QueryDSl 实体,就像常规实体一样:

JPAQuery<QAsset> query = new JPAQuery<>(entityManager);  
QBGroupByAid bGroupById = QBGroupByAid.bGroupByAid;

 List<A> tupleOfAssets =
            query.select(A)
        .from(A).innerJoin(bGroupById).on(bGroupById.aId.eq(A.aId))
        .fetchResults()
        .getResults();
        
于 2021-04-25T15:09:00.263 回答