当前位置: 首页 > 知识库问答 >
问题:

聚合子查询结果上的 JPA 聚合

燕光熙
2023-03-14

我有以下JPA实体(getter、setter和非相关字段省略):

@Entity
@Table(name = "transaction")
public class Transaction {

@Id
@GeneratedValue
@Column(name = "id")
private Long id;

@Column(name = "start_date", nullable = false)
private Date startDate;

}

我的目标是使用JPQL或criteriaAPI实现查询,它将返回每天的平均事务量和最大事务量。

产生预期结果的原生SQL查询(MySQL数据库)如下所示:

select max(cnt) from (
select date(start_date) start_date, count(t.id) cnt 
from transaction t 
group by date(t.start_date)
) t;

select avg(cnt) from (
select date(start_date) start_date, count(t.id) cnt 
from transaction t 
group by date(t.start_date)
) t;

遗憾的是,不鼓励使用本机 SQL 查询,并且 JPQL 不允许在 where 子句中使用子查询。

提前谢谢你。

附加:

我从以下Spring数据查询开始:

@Query("select max(cnt) from ("
+ "select date(t.startDate) startDate, count(t.id) cnt "
+ "from Transaction t "
+ "group by date(t.startDate))")

但显然没有用:

 org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 22 [select max(cnt) from (select date(t.startDate) startDate, count(t.id) cnt from Transaction t group by date(startDate))]

我可以想象,使用排序和限制输出可以管理max的搜索,但这对avg没有帮助。

共有1个答案

宗政洋
2023-03-14

在JPQL(或Criteria)中无法编写您想要的内容有两个原因:

  • From中的子查询,如您所指
  • 日期函数-MySQL/Hibernate特定。

对于这个查询,您可能只要求可移植性(尽可能保持原生SQL的标准化)。

一种选择是使用 FluentJPA,它消除了嵌入式字符串,并与 Java 和 JPA 紧密集成。因此,查询将如下所示:

public int getAvgCount() {

    FluentQuery query = FluentJPA.SQL(() -> {

        DailyCount daily = subQuery((Transaction t) -> {

            Date date = alias(DATE(t.getStartDate()), DailyCount::getDate);
            int count = alias(COUNT(t.getId()), DailyCount::getCount);

            SELECT(date, count);
            FROM(t);
            GROUP(BY(date));
        });

        SELECT(AVG(daily.getCount())); // or MAX
        FROM(daily);
    });

    return query.createQuery(em, Integer.class).getSingleResult();
}

类型声明:

@Tuple
@Getter // lombok
public class DailyCount {
    private Integer count;
    private Date date;
}

生成的SQL:

SELECT AVG(q0.count)
FROM (SELECT DATE(t0.start_date) AS date, COUNT(t0.id) AS count
FROM transaction t0
GROUP BY  DATE(t0.start_date)) q0
 类似资料:
  • 问题内容: 我是ORM的新手,我需要一些帮助来理解一些东西。 假设我有以下标准SQL查询: 我想在JPA中使用。 我有一个与测试实体一对多关系的检验实体。(检查有很多测试)我尝试用JPQL编写此代码: 1)如何编写COUNT子句?我必须将计数应用于测试表中的元素,但testList是一个集合,所以我不能做这样的事情 2)假设解析为1,将返回哪种类型的对象。绝对不是检查对象…如何使用结果? 问题答案

  • 我想用JPA编写以下查询,以检索按和分组的指令的计数。我知道以下SQL可以工作: 我想从这个查询中获取结果,并将其映射到一个新的对象调用: 问题所在

  • >[danger] 注意!!! 使用聚合功能时,必须给它一个别名,以便能够从模型中访问它 > 聚合函数的计算,都是排除了 null 值,所以COUNT( id ) 一般推荐用非空的主键来计算 COUNT 计算数量 const { Sequelize } = app; // 查询班级总人数,按照姓名聚合 const ret = await Student.findAll({ attribut

  • 在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数、所有用户的最大积分、用户的平均成绩等等,ThinkPHP为这些统计操作提供了一系列的内置方法,包括: 方法 说明 count 统计数量,参数是要统计的字段名(可选) max 获取最大值,参数是要统计的字段名(必须) min 获取最小值,参数是要统计的字段名(必须) avg 获取平均值,参数是要统计的字段名(必须) sum

  • 问题内容: 我想要做的是计算子查询返回的行数,本质上如下: 这是我的错误信息: 为什么这不起作用?如果select仅返回一堆具有过滤条件的行,为什么我不能计算行数或返回的行数? 我正在计算拥有的不同员工的数量。按分组。 这是有关我的数据库的一些结构信息,作为查询的一部分。 谢谢! 问题答案: 试试这个 或这个

  • 我不熟悉Mongo中的聚合查询,并且一直在努力产生我想要的输出。我有以下聚合查询: 返回以下结果: 如何修改聚合查询,以便只返回2个文档而不是3个文档?将两个“ABC-123”结果合并为一个结果,并使用带有“bu”和“count”字段的新计数数组,即。 非常感谢