I need to create a query and I need COUNT(*)
and HAVING COUNT(*) = x
.
I'm using a work around that uses the CustomProjection
class, that I downloaded somewhere.
This is the SQL that I try to achieve:
select count(*) as y0_, this_.ensayo_id as y1_ from Repeticiones this_
inner join Lineas linea1_ on this_.linea_id=linea1_.id
where this_.pesoKGHA>0.0 and this_.nroRepeticion=1 and linea1_.id in (18,24)
group by this_.ensayo_id
having count(*) = 2
This is the code, where I use the Projection
Hibernate class:
critRepeticion.setProjection(Projections.projectionList()
.add( Projections.groupProperty("ensayo") )
.add( CustomProjections.groupByHaving("ensayo_id",Hibernate.LONG,"COUNT(ensayo_id) = "+String.valueOf(lineas.size()))
.add( Projections.rowCount() )
);
The error is:
!STACK 0
java.lang.NullPointerException
at org.hibernate.criterion.ProjectionList.toSqlString(ProjectionList.java:50)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getSelect(CriteriaQueryTranslator.java:310)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:71)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:67)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1550)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
at ar.com.cse.cseagro.controller.RepeticionController.buscarEnsayo(RepeticionController.java:101)
If I comment the line with CustomProjections
class, the query work, but I don't get the HAVING COUNT(*)
filter in the SQL ...
Basically the query try to retrieve, in a master - detail schema, all the master records where a list of details are simultaneously present, like if you want tho know "which invoices have both products, A and B".
That why if I got 3 items in the IN
clause, I need to use HAVING COUNT = 3
clause.
Any idea or suggestion? Best regards,
The count() can be used to count any kind of values, including the number of rows in the query result. avg(): calculates the average of given numeric arguments. count() including count(distinct), count(all), and count(*): count the number of values/rows.
The HQL Group By clause is used to group the data from the multiple records based on one or more column. It is generally used in conjunction with the aggregate functions (like SUM, COUNT, MIN, MAX and AVG) to perform an aggregation over each group.
I figured out the problem. I replace CusotmProjections class, with:
.add( Projections.sqlGroupProjection("ensayo_id", groupBy , alias, types));
where groupBy, alias and types are:
String groupBy = "ensayo_id" + " having " + "count(*) = " + String.valueOf(lineas.size());
String[] alias = new String[1];
Alias[0] = "ensayo_id";
Type[] types = new Type[1];
types[0] = Hibernate.INTEGER;
and the magic is on groupby String. –
If someone needs to do it in grails it would be like:
projections {
groupProperty("id")
sqlGroupProjection(...)
rowCount()
}
Where sqlGroupProjection is available since 2.2.0
/**
* Adds a sql projection to the criteria
*
* @param sql SQL projecting
* @param groupBy group by clause
* @param columnAliases List of column aliases for the projected values
* @param types List of types for the projected values
*/
protected void sqlGroupProjection(String sql, String groupBy, List<String> columnAliases, List<Type> types) {
projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()])));
}
http://grepcode.com/file/repo1.maven.org/maven2/org.grails/grails-hibernate/2.2.0/grails/orm/HibernateCriteriaBuilder.java/#267
Here is my sample, it works fine, maybe useful :
My sql query :
select COLUMN1, sum(COLUMN2) from MY_TABLE group by COLUMN1 having sum(COLUMN2) > 1000;
And Criteria would be :
Criteria criteria = getCurrentSession().createCriteria(MyTable.Class);
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("column1"), "column1");
projectionList.add(Projections.sqlGroupProjection("sum(column2) sumColumn2 ", "COLUMN1 having sum(COLUMN2) > 1000" , new String[]{"sumColumn2"}, new org.hibernate.type.Type[]{StandardBasicTypes.STRING}));
criteria.setProjection(projectionList);
criteria.List();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With