如何在 QueryDSL(Java 中)中实现组计数?
背景
我正在表上实现分页搜索,我想在返回结果之前对结果进行分组。
除了平常的LIMIT x OFFSET y
查询时,我还想接收总行数。
这是一页的(简化的)SQL 查询:
SELECT x, y, MAX(z)
FROM tasks
WHERE y > 10
GROUP BY x, y
LIMIT 10 OFFSET 0
为了检索行数,我尝试使用天真的COUNT(*)
而不是x, y, MAX(z)
像这样:
SELECT COUNT(x)
FROM tasks
WHERE y > 10
GROUP BY x, y
不幸的是,这不会生成包含前一个查询返回的组数的一行,而是每个组生成一行,每个组包含分组在一起的行数 - 与聚合函数一样,COUNT
当a改变它的含义时GROUP BY
存在。 (至少在 Postgresql 中,我们在这里使用的是它。)
我们可以通过使用第一个 SELECT 语句作为 from 子句中的子查询来检索总计数:
SELECT COUNT(*)
FROM ( SELECT x, y, MAX(z)
FROM tasks
WHERE y > 10
GROUP BY x, y
)
现在是困难的部分:我们如何在 JPQL 和/或 QueryDSL 中做到这一点?
前两个查询是由如下代码生成的:
QTask qTask = QTask.task;
Expression<?>[] groupExps = { qTask.x, qTask.y };
Predicate predicate = qTask.y.gt(10);
List<Result> results = getQueryDSL().createQuery()
.from(qTask)
.where(predicate)
.groupBy(groupExps)
.offset(0)
.limit(10)
.list(ConstructorExpression.create(Result.class,
qTask.x
qTask.y,
qTask.z.max()))
Long total = getQuerydsl().createQuery()
.from(qTask)
.where(predicate)
.groupBy(groupExps)
.singleResult(qTask.x.count());
看起来像JPA/JPQL 不支持 WHERE 或 HAVING 子句之外的子选择 https://stackoverflow.com/a/6952119/600500,即它们在 FROM 子句中是不可能的。这似乎是 QueryDSL for JPA 也不支持它们的原因。
有没有办法重写这个语句,或者以某种方式解决这个限制?