0

我有以下 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 或标准 API 实现查询,它将返回每天的平均交易量和每天的最大交易量。

提供所需结果的本机 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 Data 查询开始:

@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))]

我可以想象,使用排序和限制输出可以管理搜索最大值,但这对平均值没有帮助。

4

1 回答 1

1

无法在 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
于 2019-10-13T15:39:07.053 回答