OpenJPA: how to construct a GROUP BY query with a group count - java

In JPQL I want to construct the equivalent query to this:
select *, count(*) as finger_count from page_delta_summary
where delta_history_id = ? and change_type = ? group by fingerprint;
where fingerprint is a varchar field in table page_delta_summary. What I have is this:
select d, count(d) as finger_count from PageDeltaSummary d
where d.deltaHistoryId = :deltaHistoryId and d.type = :pageDeltaType
GROUP BY d.fingerprint"
where PageDeltaSummary is my entity. But I'm getting the following exception:
org.apache.openjpa.persistence.ArgumentException: Your query on type "class com.su3analytics.sitedelta.model.PageDeltaSummary" with filter "select d, count(d) from PageDeltaSummary d where d.deltaHistoryId = :deltaHistoryId and d.type = :pageDeltaType GROUP BY d.fingerprint" is invalid. Your select and having clauses must only include aggregates or values that also appear in your grouping clause.
The query works fine if I remove either count(d) as finger_count or the GROUP BY.
Any suggestions?
Thanks

Your original SQL query doesn't make sense, therefore you can't convert in into JPQL.
I guess you want to get count of page_delta_summary rows satisfying where conditions for each fingerprint. If so, the SQL query looks like this:
select fingerprint, count(*) as finger_count from page_delta_summary
where delta_history_id = ? and change_type = ? group by fingerprint;
and JPQL - like this:
select d.fingerprint, count(d) from PageDeltaSummary d
where d.deltaHistoryId = :deltaHistoryId and d.type = :pageDeltaType
GROUP BY d.fingerprint
These queries return pairs <fingerprint, finger_count> instead of full page_delta_summary rows (or entities).

Related

Hibernate: ERROR- column must appear in the GROUP BY clause or be used in an aggregate function

I'm trying to change the SQL query to CriteriaBuilder way and facing this error.
Caused by: org.postgresql.util.PSQLException:
ERROR: column "lopcoverag0_.slot" must appear in the GROUP BY clause
or be used in an aggregate function
SQL - This query works for me when I do in the SQLWorkbench
select count(*) from (Select distinct slot from lop_coverage
where pageFamily='Gateway' and currentStatus ='Active'
and (lop in ("[en_US]","none")) group by creativeID) as totalcount;
To JPA CriteriaBuilder:
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
Root<LOPCoverage> root = criteriaQuery.from(LOPCoverage.class);
criteriaQuery.select(root.get(LOPCoverage_.slot)).distinct(true);
List<String> lopList = Arrays.asList(new String[]{"none", "[en_US]"});
Expression<String> lopExpression = root.get(LOPCoverage_.lop);
Predicate lopINPredicate = lopExpression.in(lopList);
Predicate andRestriction = criteriaBuilder.and(
criteriaBuilder.equal(root.get("pageFamily"), pageFamily),
lopINPredicate);
criteriaQuery.where(andRestriction).groupBy(root.get("creativeID"));
System.out.println( session.createQuery(criteriaQuery).list());
from hibernate logs this is the query generated
Hibernate: select distinct lopcoverag0_.slot as col_0_0_ from
lop_coverage lopcoverag0_ where lopcoverag0_.page_family=? and
(lopcoverag0_.lop in (? , ?)) group by lopcoverag0_.creative_id
I understood there is a mistake in my code in criteriaBuilder can someone tell me issue or point me to right place
Select distinct slot
this is not a aggregate function nor is it in the group by
either
select distinct group, slot
or select group, slot ... group by group, slot

QueryDSL - order by count as alias

I'm using queryDSL to get users with some additional data from base:
public List<Tuple> getUsersWithData (final SomeParam someParam) {
QUser user = QUser.user;
QRecord record = QRecord.record;
JPQLQuery = query = new JPAQuery(getEntityManager());
NumberPath<Long> cAlias = Expressions.numberPath(Long.class, "cAlias");
return query.from(user)
.leftJoin(record).on(record.someParam.eq(someParam))
.where(user.active.eq(true))
.groupBy(user)
.orderBy(cAlias.asc())
.list(user, record.countDistinct().as(cAlias));
}
Despite it's working as desired, it generates two COUNT() in SQL:
SELECT
t0.ID
t0.NAME
to.ACTIVE
COUNT(DISTINCT (t1.ID))
FROM USERS t0 LEFT OUTER JOIN t1 ON (t1.SOME_PARAM_ID = ?)
WHERE t0.ACTIVE = true
GROUP BY t0.ID, to.NAME, t0.ACTIVE
ORDER BY COUNT(DISTINCT (t1.ID))
I want to know if it's possible to get something like this:
SELECT
t0.ID
t0.NAME
to.ACTIVE
COUNT(DISTINCT (t1.ID)) as cAlias
FROM USERS t0 LEFT OUTER JOIN t1 ON (t1.SOME_PARAM_ID = ?)
WHERE t0.ACTIVE = true
GROUP BY t0.ID, to.NAME, t0.ACTIVE
ORDER BY cAlias
I failed to understand this from documentation, please, give me some directions if it's possible.
QVehicle qVehicle = QVehicle.vehicle;
NumberPath<Long> aliasQuantity = Expressions.numberPath(Long.class, "quantity");
final List<QuantityByTypeVO> quantityByTypeVO = new JPAQueryFactory(getEntityManager())
.select(Projections.constructor(QuantityByTypeVO.class, qVehicle.tipo, qVehicle.count().as(aliasQuantity)))
.from(qVehicle)
.groupBy(qVehicle.type)
.orderBy(aliasQuantity.desc())
.fetch();
select
vehicleges0_.type as col_0_0_, count(vehicleges0_.pk) as col_1_0_
from vehicle vehicleges0_
group by vehicleges0_.type
order by col_1_0_ desc;
I did something like that, but I did count first before ordering. Look the query and the select generated.
That's a restriction imposed by SQL rather than by queryDSL.
You may try to run your suggested query in a DB console - I think it won't execute, at least not on every DB.
But I don't think this duplicated COUNT() really creates any performance overhead.

Maximo setWhere() query to get distinct results?

I'm trying to do this SQL query:
select distinct wonum from invreserve where location='01' order by wonum;
How can this be converted to a setWhere() query? I've tried:
invreserveSet.setWhere("(1 = 1) and wonum in (select distinct wonum from invreserve where location='01')");
work with something like this:
select invreserveid from invreserve where invreserveid in (select invreserveid from invreserve invr2 where location like '%B%'
and invreserveid = (select max(invreserveid) from invreserve invr3 where invr3.location = invr2.location and invr3.wonum = invr2.wonum))
;
so your where clause would be the same as this ones except your location wildcard would be different.

criteria query ORDER BY yields error. Is this an SQL-SERVER limitation? How could I order by correctly on a complicated criteria query?

I have the following criteria query:
String cat = "H";
Criteria criteria = currentSession().createCriteria(this.getPersistentClass()).
add(Restrictions.ne("category", cat)).
createAlias("employees", "emp").
createAlias("emp.company", "company");
Disjunction disjunction = Restrictions.disjunction();
for(Region r: regions){
disjunction.add(Restrictions.eq("company.region", r));
}
criteria.add(disjunction);
if(status != null) {
criteria.add(Restrictions.eq("status", status));
}
if (period != null) {
criteria.add(Restrictions.eq("period", period));
}
criteria.setProjection(Projections.groupProperty("id")) //this line was added to try to "fix" the error, but it still happened.
criteria.addOrder(Order.asc("id"));
I guess a query that explains my criteria query could be:
select n.* from NOMINATION n
join NOMINEE i on n.NOM_ID = i.NOM_ID
join EMPLOYEE e on e.EMP_ID = i.EMP_ID
join COMPANY c on c.COMPANY_CODE = e.COMPANY_CODE
where n.CATEGORY_CODE!='H' and (c.REGION_ID = ? or c.REGION_ID = ? or c.REGION_ID = ?) and n.STATUS_ID = ? and n.PERIOD_ID = ?
order by n.NOM_ID
What I am trying to do here, is pretty confusing but for the most part it works except when I add this specific line (though the query works fine):
criteria.addOrder(Order.asc("id"));
and then I get error:
java.sql.SQLException: Column "NOMINATION.NOM_ID" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Which I suspect is something that has to do with SQL-SERVER. I am already grouping by id. So what am I doing wrong here, or should I just use HQL?
Your current query seems to be a simple Query which doesn't have any group function used or not a group by query. According to your current requirements you do not have to use this line.
criteria.setProjection(Projections.groupProperty("id")).addOrder(Order.asc("id"));
Or you have to modify your sql statements.

How do I rewrite this particular JPQL query with SELECT MAX() to CriteriaQuery?

I am quite new to JPA and I have encountered a problem with understanding one particular query. I have rewritten in to the CriteriaQuery but the result and the query translated to SQL is not correct.
Background situation: I have a table of store transaction (moves) and the current amount in the store is defined as a sum of all changes. Now I want to select and display the last moves as they also contain an information about the resulting amount on store.
So, this is the query in JPQL:
SELECT m FROM move m WHERE m.id = (
SELECT MAX(o.id) FROM move o WHERE (o.item = m.item AND m.cell.store = :s)
I tried to rewrite it to the following CriteriaQuery:
CriteriaBuilder builder = model.getCriteriaBuilder();
CriteriaQuery<Move> query = builder.createQuery(Move.class);
Root<Move> root = query.from(Move.class);
Subquery<Long> subquery = query.subquery(Long.class);
Root<Move> subroot = subquery.from(Move.class);
subquery.select(builder.max(subroot.get("id").as(Long.class)));
subquery.where(builder.and(
builder.equal(
subroot.get("item").get("id"),
root.get("item").get("id")),
builder.equal(
subroot.get("cell").get("store").as(Store.class),
store)));
Expression<Boolean> where = builder.equal(
root.get("id"),
subquery);
query.where(where);
return model.getList(query);
The incorrect SQL query produced is following:
SELECT t0.id, (...) FROM move t0 WHERE (t0.id = (
SELECT MAX(t1.id) FROM item t3, item t2, move t1
WHERE (((t2.id = t3.id) AND
(t1.cell_store = ?)) AND
((t2.id = t1.item_ref) AND
(t3.id = t0.item_ref))))
)
I do not understand why there is a double cross join in the subquery. Thank you for helping!

Categories