Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HQL: group by month

I'm trying to group by month some rows using HQL, but I'm kind of new to that API and can't seem to get it to work.

Here is my code:

        Criteria query = getHibernateSession().createCriteria(SalesPerformance.class);

        // summary report is grouped by date
        query.setProjection(Projections.projectionList().add(
                Projections.groupProperty("effectiveDate"), "effectiveDate").add(
                Projections.groupProperty("primaryKey.seller", "seller").add(
                Projections.sum("totalSales"))));


        // sub-select based on seller id
        query.add(Property.forName("primaryKey.seller.id").eq(sellerId)).setFetchMode(
                "primaryKey.seller", FetchMode.SELECT);

        query.add(Property.forName("primaryKey.effectiveDate").le(new Date()));
        query.add(Property.forName("primaryKey.effectiveDate").ge(DateUtils.truncate(new Date(), Calendar.MONTH)));
        query.addOrder(Order.desc("primaryKey.effectiveDate"));

        return query.list();

My problem with this query is that it's going to return one row per day when I need one row per month because of Projections.groupProperty("effectiveDate").

I thought about using Projections.sqlGroupProjection instead of Projections.groupProperty and throw in some HQL, but the documentation and the couple examples I found didn't really help me understand how I would go about putting the right postresql statement in that method.

Anyone who knows about Postgres and HQL could give some hints here please?

like image 436
Lancelot Avatar asked Jan 01 '26 06:01

Lancelot


1 Answers

Found the solution:

Criteria query = getHibernateSession().createCriteria(SalesPerformance.class);

    // summary report is grouped by date
            query.setProjection(Projections.projectionList().add(Projections.sqlGroupProjection("date_trunc('month', eff_dt) as eff_dt_value", "eff_dt_value", new String[] {"eff_dt_value"}, new Type[] {Hibernate.DATE})).add(
                            Projections.groupProperty("primaryKey.seller", "seller").add(
                            Projections.sum("totalSales"))));


            // sub-select based on seller id
            query.add(Property.forName("primaryKey.seller.id").eq(sellerId)).setFetchMode(
                            "primaryKey.seller", FetchMode.SELECT);

            query.add(Property.forName("primaryKey.effectiveDate").le(new Date()));
            Date beginningOfLastMonth = DateUtils.truncate(DateUtils.addMonths(new Date(), -1) , Calendar.MONTH);
            Date endOfLastMonth = DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.MONTH), -1);
            query.add(Property.forName("primaryKey.effectiveDate").between(beginningOfLastMonth, endOfLastMonth));


            return query.list();

Please note that in my case I need to grab values with effectiveDate from last month.

Hopefully that will help others in the same boat! :)

like image 169
Lancelot Avatar answered Jan 05 '26 06:01

Lancelot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!