Available in versions: Dev (3.19) | Latest (3.18) | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11 | 3.10 | 3.9
SEMI JOIN
Applies to ✅ Open Source Edition ✅ Express Edition ✅ Professional Edition ✅ Enterprise Edition
Relational algebra defines a SEMI JOIN
operation that regrettably didn't make it into standard SQL (yet), though it is easy to emulate using the EXISTS predicate or IN predicate, which is what most people are doing.
jOOQ offers a convenient LEFT SEMI JOIN
operator to match the relational algebra semantics. The following query will produce all authors that have books (but doesn't produce any books):
SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME FROM AUTHOR WHERE EXISTS ( SELECT * FROM BOOK WHERE BOOK.AUTHOR_ID = AUTHOR.ID )
create.select( AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME ) .from(AUTHOR) .leftSemiJoin(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .fetch();
The result might look like this:
+------------+-----------+ | FIRST_NAME | LAST_NAME | +------------+-----------+ | George | Orwell | | Paulo | Coelho | +------------+-----------+
Of course, you can form an equivalent query using EXISTS
or IN
as well in jOOQ. It is also possible to achieve SEMI JOIN
semantics by using an INNER JOIN, and possibly the SELECT DISTINCT
clause, but chances are, that query is slower and incorrect (e.g. removing too many distinct rows). A SEMI JOIN
both using jOOQ's convenience syntax or the equivalent SQL emulation using EXISTS
or IN
are semantically more precise and should be preferred.
SEMI JOIN
is the inverse of the ANTI JOIN operator.
Dialect support
This example using jOOQ:
select(AUTHOR.ID).from(AUTHOR).leftSemiJoin(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID))
Translates to the following dialect specific expressions:
-- All dialects SELECT AUTHOR.ID FROM AUTHOR WHERE EXISTS ( SELECT 1 one FROM BOOK WHERE BOOK.AUTHOR_ID = AUTHOR.ID )
(These are currently generated with jOOQ 3.19, see #10141), or translate your own on our website
References to this page
Feedback
Do you have any feedback about this page? We'd love to hear it!