Question

In my Java Web application I use Postgresql and some data tables are filled automatically in server. In the database I have a STATUS table like below:

enter image description here

I want to select the data related to a vehicle between selected dates and where the vehicle stayed connected. Simply I want to select the data which are green in the above table which means I exactly want the data when firstly io1=true and the data when io1=false after the last io1=true. I have postgresql query statement which exactly gives me the desired data; however, I have to convert it to HQL because of my application logic.

working postgresql query:

WITH cte AS
( SELECT iostatusid, mtstrackid, io1,io2,io3, gpsdate,
       (io1 <> LAG(io1) OVER (PARTITION BY mtstrackid
                                          ORDER BY gpsdate)
       ) AS status_changed
FROM iostatus 
WHERE mtstrackid = 'redcar' AND gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59' 
) 
SELECT iostatusId, mtstrackid, io1, io2, io3,gpsdate
FROM cte
WHERE status_changed 
OR io1 AND status_changed IS NULL 
ORDER BY gpsdate ;

How should I convert the above query to HQL or how could I retrieve the desired data with HQL?

No correct solution

OTHER TIPS

The goal of hibernate is mapping database entities to java objects. This kind of complex queries are not entities themselves. This is against the spirit of hibernate.

If this query generates an entity in your application logic, I recommend putting the results into a table and applying Hibernate queries to that table.

If this query generates some kind of aggregation or summary, there are two possible ways:

  • One way is you compute this aggregation/summary in your application after retrieving entities from iostatus table with hibernate.

  • If this query has nothing to do with your application logic then you can use Native SQL interface of Hibernate and execute the query directly. (You can even use JPA if you are willing to manipulate two database connections.)

If you absolutely need to convert it to HQL, you need to eliminate the partition function. If the order of iostatusId is identical to the order of gpsdate, you can do it similar to

SELECT i2.*
FROM iostatus i1 
INNER JOIN iostatus i2 ON i1.iostatusId = i2.iostatusId - 1 
                      AND i1.io1 <> i2.io1 
                      AND i1.mstrackid = i2.mstrackid
WHERE i2.mtstrackid = 'redcar' AND 
       i2.gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59'

If gpsdate is no way related to iostatusId then you need something like

SELECT i2.*
FROM iostatus i1 
INNER JOIN iostatus i2 ON i1.gpsdate < i2.gpsdate
                      AND i1.io1 <> i2.io1 
                      AND i1.mstrackid = i2.mstrackid
WHERE i2.mtstrackid = 'redcar' AND 
      i2.gpsdate between '2014-02-28 00:00:00' and '2014-02-28 23:59:59' AND 
      NOT EXISTS (SELECT * FROM iostatus i3 
                  WHERE i3.gpsdate > i1.gpsdate AND 
                        i2.gpsdate > i3.gpsdate AND
                        i3.io1 = i1.io1 AND 
                        i1.mstrackid = i3.mstrackid)

I guess both of the queries can be converted to HQL, but I'm not positively sure.

By the way I must warn you that, these methods might not perform better then finding the changes in your application, because they involve joining the table onto itself, which is an expensive operation; and the second query involves a nested query after the join, which is also quite expensive.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top