Reputation: 331
I currently have a query like this:
SELECT DISTINCT t.column1, SUM(t2.column2 IS NOT NULL)
FROM table t
LEFT OUTER JOIN table t2 on table.id = t2.id
GROUP BY column1, column2;
I am trying to implement the query using Spring JPA CriteriaBuilder. I see the CriteriaBuilder.sum() method, but I don't see a way to apply the IS NOT NULL part to the selection. Column2's data type is string.
Sample of my code
criteriaBuilder.multiselect(root.get("column1"), cb.sum(root.get("column2")));
Upvotes: 4
Views: 1745
Reputation: 331
I was able to find a solution to my problem. Thanks to @bohemian for helping me write a correct sum expression.
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Model1> cq = cb.createQuery(Model1.class);
final Root<Model1> root = cq.from(Model1.class);
final Join<Model1, Model1> selfJoin =
root.join("tableJoinColumn", JoinType.LEFT);
selfJoin.on(...);
cq.multiselect(root.get("column1"), cb.sum(cb.selectCase()
.when(cb.isNull(selfJoin.get("column2")), 0).otherwise(1).as(Long.class)));
...
The self join required me to create an additional property on my model. Model1.java
/**
* Property for LEFT INNER JOIN.
*/
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="id")
private Model1 tableJoinColumn;
How to use JPA CriteriaBuilder selectCase() so that it can have Predicate as result?
Upvotes: 1
Reputation: 425448
Only in MySQL would such a query run, due MySQL’s relaxed syntax rules.
In particular, in mysql sum(column2 is not null)
is a count, not a sum. The expression column2 is not null
is boolean and in mysql false is 0 and true is 1, so summing this expression is a mysql hack to count the number of times column2 is not null.
To convert it to standard sql:
select
t.column1,
count(t2.column2)
from table t
left join table t2 on t.id = t2.id
group by t.column1
This works because count()
(and all aggregate functions) ignore nulls.
This version also corrects the errant column in the group by
clause - in any other database, your query would have produced a “grouping by aggregate expression” error.
This query will produce the same result in MySQL as your current query.
Upvotes: 2