JPA标准查询以查找每个唯一名称的MAX ID

时间:2018-11-19 03:36:45

标签: sql jpa jpa-2.0 criteria-api

编辑:显然我之前的问题还不够,所以我将通过这次尝试使它更加清楚。

我在表中有一组行,由谓词 p1 选择,每行在 id 列中具有唯一值。 pathName 列可能包含多个具有相同值的实例。想要的是仅返回具有唯一的 pathName 且具有最高值 id 的实体。

 CriteriaBuilder builder = em.getCriteriaBuilder();
 CriteriaQuery<TextDocument> query = builder.createQuery(TextDocument.class);
 Root<TextDocument> root = query.from(TextDocument.class);

 // descending ids, and group similar names together

 query.orderBy(builder.desc(root.get(TextDocument_.id)));
 query.groupBy(root.get(TextDocument_.pathName));

 // filter

 Predicate p1 = builder.equal(root.get(TextDocument_.parent), rootdoc);
 Predicate p2 = builder.equal(root.get(TextDocument_.id), builder.max(root.get(TextDocument_.id)));
 query.where(p1, p2);

谓词 p1 选择所有具有相同父文档的文档,并且只要它本身就可以工作。

但是,

谓词 p2 是错误的。添加它会导致异常错误42903:聚合函数的无效使用。

类似的查询问题的解决方案在SQL中显示为here,但我想使用JPA标准查询来完成。我不知道如何使嵌套的SELECT语法起作用。

为重申我自己的示例中的问题,我具有以下数据集

id  parent  pathName  
--- ------- --------- 
101     22  alpha
130     22  beta
250     22  charlie
251     22  alpha
339     22  beta
400     22  alpha
401     22  delta

正确的结果(对于parent = 22)将是:

id  parent  pathName  
--- ------- --------- 
250     22  charlie
339     22  beta
400     22  alpha
401     22  delta

有人可以帮我完成此查询吗?

2 个答案:

答案 0 :(得分:1)

将Reza示例用于sql:

SELECT * from [tableName] t1
WHERE not exists(SELECT * from [tableName]t2 where t1.name = t2.name and t2.id > t1.id)

并假设现有的Root 根,CriteriaQuery <?>条件查询,CriteriaBuilder条件构建器,则可以编写JPA条件:

Subquery<TableEntity> subQuery = criteriaQuery.subquery(TableEntity.class);
Root<TableEntity> subQueryRoot = subQuery.from(TableEntity.class);
subQuery.select(subQueryRoot)
        .where(criteriaBuilder.and(
                criteriaBuilder.equal(subQueryRoot.get(TableEntity_.name), root.get(TableEntity_.name)),
                criteriaBuilder.greaterThan(subQueryRoot.get(TableEntity_.id), root.get(TableEntity_.id))
        ));
predicates.add(criteriaBuilder.not(criteriaBuilder.exists(subQuery)));

答案 1 :(得分:0)

你可以做到

SELECT * from [tableName] t1
WHERE not exists(SELECT * from [tableName]t2 where t1.name = t2.name and t2.id > t1.id)