Unable to use lateral join

91 views
Skip to first unread message

Stefan Sator

unread,
Oct 3, 2023, 4:04:01 AM10/3/23
to jOOQ User Group
Hello Lukas,

how do I write this query correctly?

Wanted:
SELECT o.name, l.comment
FROM customerobjectdb_object AS o,
LATERAL (SELECT * FROM customerobjectdb_history AS h WHERE h.object_id = o.id
order by h.major_version desc, h.minor_version desc limit 1
) AS l
ORDER BY o.id;

Jooq(not correct)
var fetch = db.select(o.NAME,
//o.STATUS.convertFrom(x -> ObjectSafetyStatus.from(x)),
//o.CHANGED_AT,
//o.VERSION,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as("l")
)
.from(o)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();

SQL
select "o"."name", row ("l"."comment") as "l"
from "public"."customerobjectdb_object" as "o"
order by "o"."changed_at" desc fetch next ? rows only



jooqQuery.png
wantedQuery.png
falseQuery.png

Lukas Eder

unread,
Oct 3, 2023, 4:09:53 AM10/3/23
to jooq...@googlegroups.com
Why put your LATERAL derived table in SELECT with jOOQ, when you don't do that with SQL?

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/38f093bf-1ac6-4317-8e19-032eea82685bn%40googlegroups.com.

Stefan Sator

unread,
Oct 3, 2023, 4:18:22 AM10/3/23
to jOOQ User Group
Because I get sometimes confused.
I figured that out aswell just now before reading your comment :-)

But how do I select only some of the columns from the lateral join?

var fetch = db.select()
.from(o,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as("l")
)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();

Lukas Eder

unread,
Oct 3, 2023, 4:28:05 AM10/3/23
to jooq...@googlegroups.com

Stefan Sator

unread,
Oct 3, 2023, 4:44:43 AM10/3/23
to jOOQ User Group
This works, but it doesnt look elegant.

Is there a better way?

CustomerobjectdbObject o = CustomerobjectdbObject.CUSTOMEROBJECTDB_OBJECT.as("o");
CustomerobjectdbHistory h = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("h");
CustomerobjectdbHistory l = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("l");

//@formatter:off
var fetch = db.select(o.NAME, l.field("comment"))

.from(o,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as("l")
)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();

Stefan Sator

unread,
Oct 3, 2023, 4:47:12 AM10/3/23
to jOOQ User Group
Final solution:

CustomerobjectdbObject o = CustomerobjectdbObject.CUSTOMEROBJECTDB_OBJECT.as("o");
CustomerobjectdbHistory h = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("h");
CustomerobjectdbHistory l = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("l");

//@formatter:off
var fetch = db.select(o.NAME, l.field("comment"))
.from(o,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as(l)
)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();

Stefan Sator

unread,
Oct 3, 2023, 4:49:33 AM10/3/23
to jOOQ User Group
And even better:

CustomerobjectdbObject o = CustomerobjectdbObject.CUSTOMEROBJECTDB_OBJECT.as("o");
CustomerobjectdbHistory h = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("h");
CustomerobjectdbHistory l = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("l");

//@formatter:off
var fetch = db.select(o.NAME, l.COMMENT)

.from(o,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as(l)
)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();

Stefan Sator

unread,
Oct 4, 2023, 8:32:28 AM10/4/23
to jOOQ User Group
Hi Lukas,
I dont get it to work for just some fields of the lateral join.

How do I do this?
public List<HomeShopTableUIModel> getShopPage() {
ShopdbObject o = ShopdbObject.SHOPDB_OBJECT;
ShopdbHistorie h = ShopdbHistorie.SHOPDB_HISTORIE;
ShopdbHistorie l = ShopdbHistorie.SHOPDB_HISTORIE;

Condition c = getTenantCondition(o);

//@formatter:off
var fetch = db.select(o.NAME)

.from(o,
lateral(DSL.select(h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as("l")
)
.where(c)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch();
//@formatter:on

Lukas Eder

unread,
Oct 4, 2023, 8:43:45 AM10/4/23
to jooq...@googlegroups.com
Stefan,

What is your specific question? What have you tried? What didn't work?

Stefan Sator

unread,
Oct 4, 2023, 9:17:20 AM10/4/23
to jOOQ User Group
After lots of try and error this works, but is it the "correct" way?

CustomerobjectdbObject o = CustomerobjectdbObject.CUSTOMEROBJECTDB_OBJECT.as("o");
CustomerobjectdbHistory h = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("h");
CustomerobjectdbHistory l = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("l");

Condition c = getTenantCondition(o);

//@formatter:off
var fetch = db.select(o.NAME,
o.STATUS.convertFrom(x -> ObjectSafetyStatus.from(x)),
o.CHANGED_AT,
l.MAJOR_VERSION,
l.MINOR_VERSION,
l.COMMENT)
.from(o,
lateral(DSL.select(h.MAJOR_VERSION,
h.MINOR_VERSION,
h.COMMENT)
.from(h)
.where(h.OBJECT_ID.eq(o.ID))
.orderBy(h.MAJOR_VERSION.desc(),
h.MINOR_VERSION.desc())
.limit(1)).as(l)
)
.where(c)
.orderBy(o.CHANGED_AT.desc())
.limit(10)
.fetch(mapping((r1, r2, r3, r4, r5, r6) -> new HomeObjectTableUIModel(r1, r2, r3, r4, r5, r6)));
//@formatter:on

return fetch;

Lukas Eder

unread,
Oct 4, 2023, 9:48:50 AM10/4/23
to jooq...@googlegroups.com
Let me rephrase my previous question:

What is your specific question? Why do you have doubts? What kind of answer are you expecting?

Stefan Sator

unread,
Oct 4, 2023, 1:25:24 PM10/4/23
to jOOQ User Group
At first I was unsure it there really is not other way to write:
CustomerobjectdbHistory h = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("h");
CustomerobjectdbHistory l = CustomerobjectdbHistory.CUSTOMEROBJECTDB_HISTORY.as("l");

But now I think it makes sense and is the only way to get both type safety and to be able to rename a table at the same time.

Lukas Eder

unread,
Oct 5, 2023, 3:50:26 AM10/5/23
to jooq...@googlegroups.com
You probably mean the declaration of aliased tables up front, instead of embedded in the query, like in SQL? There's no other way to declare variables in Java. Java can't follow SQL's syntax where stuff is referenced before it is declared (lexically).

Stefan Sator

unread,
Oct 8, 2023, 2:54:13 PM10/8/23
to jOOQ User Group
Thanks Lukas!
Reply all
Reply to author
Forward
0 new messages