简体   繁体   中英

criteria API predicate: group by on one column, find row min on another and then return third

I've got table

CREATE TABLE stp2_vehicles.can_data (
    id bigserial NOT NULL,
    receive_time timestamp NOT NULL,
    gps_frame_id int8 NULL
);

based on it I need to add criteria predicate required for bigger query. What i need in where clausule is select returning ids of can_data - only one id for each gps frame the one with earliest timestamp.

So in sql it would look like this:

select cd.id 
from stp2_vehicles.can_data cd
right join
        (select gps_frame_id, min(receive_time) as min_time
        from stp2_vehicles.can_data
        group by gps_frame_id
        ) cd2 on cd.gps_frame_id = cd2.gps_frame_id and cd.receive_time = cd2.min_time
;

unfortunately criteria api doesn't support joining with result of subquery.

I've tried also approach with self join (should be supported by criteria api) but solution I came with seems too computationally complex or has errors I can't see:

select cd.id
from stp2_vehicles.can_data cd
inner join stp2_vehicles.can_data cd2 on cd.id=cd2.id
where cd.receive_time = (select min(receive_time) from stp2_vehicles.can_data cd3 where cd.gps_frame_id = cd3.gps_frame_id );

By the way: I've managed to solve simpler case:

select min(cd.id) from can_data cd group by cd.gps_frame_id
CriteriaQuery<CANData> criteriaQueryCanData = cb.createQuery(CANData.class);
Subquery<Long> subquery = criteriaQueryCanData.subquery(Long.class);
Root<CANData> canDataSubRoot = subquery.from(CANData.class);
subquery
    .select(cb.least(canDataSubRoot.<Long>get(CANData_.ID)))
    .groupBy(canDataSubRoot.<Long>get(CANData_.GPS_FRAME));

Since the subquery seems to be "static", you can define an entity for the result of the subquery by using the @Subselect annotation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM