如何使用QueryDSL从子查询平均值集合中计算总平均值
解决方案
你需要将原有的分组查询作为子查询嵌套在外层查询的from子句中即可实现等效原生SQL的效果,完整实现代码如下:
import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.NumberExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQuery; public Double calculateTotalAvgQuality() { QSearchRequestItem requestItem = QSearchRequestItem.searchRequestItem; // 构造内层子查询:对应原生SQL的group by部分 var innerSubQuery = JPAExpressions .select( requestItem.quality.avg().as("avg_quality"), requestItem.user.countDistinct().as("user_count") ) .from(requestItem) .groupBy(requestItem.request) .having( requestItem.quality.avg().isNotNull(), requestItem.user.countDistinct().gt(2) ); // 构造外层查询:计算子查询结果中avg_quality的总平均值 NumberExpression<Double> avgQualityField = Expressions.numberTemplate(Double.class, "{0}", innerSubQuery.get("avg_quality")); // 直接返回最终计算结果,如需返回JPAQuery对象可删除fetchOne()并修改返回值类型 return queryFactory .select(avgQualityField.avg()) .from(innerSubQuery) .fetchOne(); }
注意事项
- 该实现依赖JPA提供商对
FROM子句子查询的支持:Hibernate 5.1及以上版本原生支持该特性,其他JPA实现请提前确认兼容性 - 原有代码中的
leftJoin(requestItem.user, user)可以省略,requestItem.user.countDistinct()会自动生成count(distinct user_id)的SQL语句,无需额外关联用户表 - 如果你使用的QueryDSL版本低于4.x,可将
JPAExpressions替换为new JPASubQuery()构造子查询,逻辑完全一致
内容的提问来源于stack exchange,提问作者jlemon
相关产品推荐
相关产品推荐

