[英]`SELECT COUNT(*) FROM (SELECT DISTINCT …)` in Hibernate or JPA
对于Hibernate或JPA来说,这似乎是一个琐碎的用例,但是我已经努力了几天,才能使它正常工作。
我有一个position
实体类,其中包含latitude
, longitude
和updateTime
字段(以及其他字段)。 我想计算这三个字段的不同组合的数量,而忽略其他字段。 在SQL中,这很简单:
SELECT COUNT(*) FROM (SELECT DISTINCT LONGITUDE, LATITUDE, UPDATE_TIME FROM POSITION) AS TEMP;
从应用程序的其余部分抽象myh数据库实现很重要,因为不同的用户可能希望使用不同的数据库引擎。 (哎呀,我使用h2进行测试,并使用mariadb进行本地生产...)
我一直在尝试使用Hibernate或JPA语法将此SQL转换为Java代码,但我不知道该怎么做。
编辑-这是我使用JPA所能获得的效果(参考: https : //en.wikibooks.org/wiki/Java_Persistence/Criteria )
public long getCountDistinctInFlightPositions() {
Session session = sessionFactory.openSession();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Tuple> innerQuery = criteriaBuilder.createTupleQuery();
Root<Position> position = innerQuery.from(Position.class);
innerQuery.multiselect(
position.get("longitude"),
position.get("latitude"),
position.get("updateTime")
);
// The method countDistinct(Expression<?>) in the type CriteriaBuilder is not applicable for the arguments (CriteriaQuery<Tuple>)
criteriaBuilder.countDistinct(innerQuery);
return 1;
}
您可以这样操作:
CriteriaQuery<Long> countQuery = cb.createQuery( Long.class );
Root<Position> root = countQuery.from( Position.class );
countQuery.select( cb.count( root.get( "id" ) ) );
Subquery<Integer> subQuery = countQuery.subquery( Integer.class );
Root<Position> subRoot = subQuery.from( Position.class );
subQuery.select( cb.min( subRoot.get( "id" ) ) );
subQuery.groupBy( subRoot.get( "longitude" ),
subRoot.get( "latitude" ),
subRoot.get( "updateTime" ) );
countQuery.where( root.get( "id" ).in( subQuery ) );
Long count = entityManager.createQuery( countQuery ).getSingleResult();
这有效地生成以下SQL:
SELECT COUNT( p0.id ) FROM Position p0
WHERE p0.id IN (
SELECT MIN( p1.id )
FROM Position p1
GROUP BY p1.longitude, p1.latitude, p1.updateTime )
在我有3行并且其中2行具有相同的经度,纬度和更新时间元组的情况下,查询将返回结果2。
确保在此处[Longtitude,Latitude,UpdateTime]上保持良好的索引,以便可以利用更快的GROUP BY执行优势。 PK已经被b树索引了,所以其他操作COUNT / MIN应该已经由该索引轻松地进行了解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.