简体   繁体   English

如何计算 QueryDSL 中结果组的数量?

[英]How can I count the number of result groups in QueryDSL?

How can I implement a count-of-groups in QueryDSL (in Java)?如何在 QueryDSL(Java)中实现组计数?

Background背景

I'm implementing a paged search on a table, where I want to group the results before returning them.我正在表上实现分页搜索,我想在返回结果之前对结果进行分组。

In addition to the usual LIMIT x OFFSET y query, I also want to receive the total row count.除了通常的LIMIT x OFFSET y查询之外,我还想接收总行数。

This is the (simplified) SQL query for one page:这是一页的(简化的)SQL 查询:

SELECT x, y, MAX(z)
  FROM tasks
 WHERE y > 10
 GROUP BY x, y
 LIMIT 10 OFFSET 0

To retrieve the number of rows, I tried to use a naive COUNT(*) instead of the x, y, MAX(z) like this:为了检索行数,我尝试使用简单的COUNT(*)而不是x, y, MAX(z)如下所示:

SELECT COUNT(x)
  FROM tasks
 WHERE y > 10
 GROUP BY x, y

Unfortunately, this doesn't produce one row with the number of groups returned by the previous query, but one row for each group, each with the number of rows which were grouped together – as usual for aggregation functions, COUNT changes its meaning when a GROUP BY is present.不幸的是,这并不能产生一个行与前面的查询返回的组数,而是一排为一组,每一个与被组合在一起的行数-像往常一样聚集功能, COUNT改变其含义时, GROUP BY存在。 (At least in Postgresql, what we are using here.) (至少在 Postgresql 中,我们在这里使用的是什么。)

We can retrieve the total count by using the first SELECT statement as a subselect in a from clause:我们可以通过使用第一个 SELECT 语句作为 from 子句中的子选择来检索总计数:

SELECT COUNT(*)
FROM ( SELECT x, y, MAX(z)
         FROM tasks
        WHERE y > 10
        GROUP BY x, y
     )

Now the hard part: how can we do this in JPQL and/or QueryDSL?现在是困难的部分:我们如何在 JPQL 和/或 QueryDSL 中做到这一点?

The first two queries are were produced by code like this:前两个查询是由如下代码生成的:

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());

It looks like JPA/JPQL doesn't support subselects other than in WHERE or HAVING-clauses , ie they are not possible in the FROM clause.看起来JPA/JPQL 不支持 WHERE 或 HAVING-clauses 以外的子选择,即它们在 FROM 子句中是不可能的。 This seems to be the cause that QueryDSL for JPA doesn't support them either.这似乎是 QueryDSL for JPA 也不支持它们的原因。

Is there a way to rewrite this statement, or somehow work around this limitation?有没有办法重写这个语句,或者以某种方式解决这个限制?

I can't help you out with jpa and jql, but it's an interesting SQL problem...我不能帮你解决 jpa 和 jql,但这是一个有趣的 SQL 问题......

What RDMS?什么RDMS? The below works in MS SQL Server.以下适用于 MS SQL Server。 You can use concatenation, distinct and count to determine how many unique values there are when you concatenate x and y.您可以使用串联、distinct 和 count 来确定串联 x 和 y 时有多少唯一值。 This should be the same number of rows when you group by x,y.当您按 x,y 分组时,这应该是相同的行数。

select count(distinct CAST(x as char(10)) + CAST(y as char(10)))
from tasks;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM