final SelectQuery<Record1<Integer>> instanceQuery = using.selectCount().getQuery();
instanceQuery.addFrom(INST);
instanceQuery.addJoin(ACTIVITY, INST.DBID_.equal(ACTIVITY.INSTANCE_DBID_));
instanceQuery.addConditions(ACTIVITY.DBID_.equal(
select(ACTIVITY_1.DBID_)
.from(ACTIVITY_1)
.where(INST.DBID_.equal(ACTIVITY_1.INSTANCE_DBID_))
.orderBy(ACTIVITY_1.ACTIVITY_ID_.desc())
.limit(1)));
This is what is generated:
select count(*)
from NOVA_PROCESS_INST INST
join NOVA_ACTIVITY_INST ACTIVITY
on INST.DBID_ = ACTIVITY.INSTANCE_DBID_
where (
ACTIVITY.DBID_ = (
select V0 DBID_
from (
select
X.V0,
rownum RN
from (
select ACTIVITY_1.DBID_ V0
from NOVA_ACTIVITY_INST ACTIVITY_1
where (
INST.DBID_ = ACTIVITY_1.INSTANCE_DBID_
)
order by ACTIVITY_1.ACTIVITY_ID_ desc
) X
where rownum <= (0 + 1)
)
where RN > 0
)
);
select count(*)
from NOVA_PROCESS_INST INST
join NOVA_ACTIVITY_INST ACTIVITY
on INST.DBID_ = ACTIVITY.INSTANCE_DBID_
where (
ACTIVITY.DBID_ = (
select V0 DBID_
from (
select
X.V0,
rownum RN
from (
select ACTIVITY_1.DBID_ V0
from NOVA_ACTIVITY_INST ACTIVITY_1
where (
INST.DBID_ = ACTIVITY_1.INSTANCE_DBID_
)
order by ACTIVITY_1.ACTIVITY_ID_ desc
) X
where rownum <= (0 + 1)
)
where RN > 0
)
);
You could write this:
select count(*)
from NOVA_PROCESS_INST INST
join (
select V0 DBID_ from ( select X.V0, rownum RN from ( select ACTIVITY_1.DBID_ V0 from NOVA_ACTIVITY_INST ACTIVITY_1
order by ACTIVITY_1.ACTIVITY_ID_ desc ) X where rownum <= (0 + 1) ) where RN > 0
) ACTIVITY
on INST.DBID_ = ACTIVITY.INSTANCE_DBID_
Or simpler, without the Oracle-specific emulated SQLselect count(*)
from NOVA_PROCESS_INST INST
join (
select ACTIVITY_1.DBID_ V0 from NOVA_ACTIVITY_INST ACTIVITY_1
order by ACTIVITY_1.ACTIVITY_ID_ desc limit 1 ) ACTIVITY
on INST.DBID_ = ACTIVITY.INSTANCE_DBID_
I hope this helps, Lukas
--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hello Lukas,
Thanks for your answer.
It seems that I oversimplified my query to present reproduction steps.
I need to have the first activity for each instance that fulfills some criteria.
I did work around the bug using a derived table like you suggested, but inside the derived table I GROUP BY ACTIVITY.INSTANCE_DBID_ and try to select a unique row for each group (using a pretty bad hack that I am not happy with).
François
PS : Just out of curiosity (this might not solve this particular problem), but why don’t you emulate limit offset in Oracle with a window function like you do in DB2 and SQL SERVER 2008 ?
Hello Lukas,
Thanks for your answer.
It seems that I oversimplified my query to present reproduction steps.
I need to have the first activity for each instance that fulfills some criteria.
I did work around the bug using a derived table like you suggested, but inside the derived table I GROUP BY ACTIVITY.INSTANCE_DBID_ and try to select a unique row for each group (using a pretty bad hack that I am not happy with).
PS : Just out of curiosity (this might not solve this particular problem), but why don’t you emulate limit offset in Oracle with a window function like you do in DB2 and SQL SERVER 2008 ?
Hello Lukas,
I'm curious, what's that hack, and why aren't you happy with it?
I need only the first activity (ordered by date) for each instance that fulfills some criteria.
So I tried something like this (again, simplified, because it normally it involves some other joined tables):
SELECT count(*)
FROM NOVA_PROCESS_INST AS INST
JOIN NOVA_ACTIVITY_INST AS ACTIVITY
ON INST.DBID_ = ACTIVITY.INSTANCE_DBID_
JOIN (
SELECT
max(ACTIVITY_1.READYDATE_) AS MAX,
ACTIVITY_1.INSTANCE_DBID_ AS ACTIVITYINSTANCE_DBID_
FROM NOVA_ACTIVITY_INST AS ACTIVITY_1
GROUP BY ACTIVITY_1.INSTANCE_DBID_
) AS ACTIVITYQUERY
ON (
INST.DBID_ = ACTIVITYQUERY.ACTIVITYINSTANCE_DBID_
AND ACTIVITY.READYDATE_ = ACTIVITYQUERY.MAX
)
ORDER BY ACTIVITY.READYDATE_ DESC
LIMIT 10;
However, it turns out that the date criteria is not specific enough, multiple rows can have the same date. So I had to have more specific data in max(…). So I did this “hack”:
SELECT count(*) FROM NOVA_PROCESS_INST AS INST JOIN NOVA_ACTIVITY_INST AS ACTIVITY ON INST.DBID_ = ACTIVITY.INSTANCE_DBID_ JOIN ( SELECT max((cast(ACTIVITY_1.READYDATE_ AS VARCHAR) || cast(ACTIVITY_1.DBID_ AS VARCHAR))) AS MAX, ACTIVITY_1.INSTANCE_DBID_ AS ACTIVITYINSTANCE_DBID_ FROM NOVA_ACTIVITY_INST AS ACTIVITY_1 GROUP BY ACTIVITY_1.INSTANCE_DBID_ ) AS ACTIVITYQUERY ON ( INST.DBID_ = ACTIVITYQUERY.ACTIVITYINSTANCE_DBID_ AND (cast(ACTIVITY.READYDATE_ AS VARCHAR) || cast(ACTIVITY.DBID_ AS VARCHAR)) = ACTIVITYQUERY.MAX ) ORDER BY ACTIVITY.READYDATE_ DESC LIMIT 10;
Good question. At some point, we did emulate Oracle's limit offset using window functions as this made things simpler in jOOQ's internals. But it turns out that ROW_NUMBER() OVER() is much less easily optimisable than ROWNUM, especially when queries get very nasty. Some details can be seen in this interesting benchmark here:And the relevant discussion here on the user group:In fact, I think it would be worth referencing the above benchmark also from the jOOQ manual. It's really interesting to see the substantial performance impact of the different approaches to pagination.Hope this helps,Lukas