jOOQ - 加入嵌套子查询
jOOQ - join with nested subquery
假设我想找出谁在一本书 db 中写了 CLRS
(tables BOOK
, AUTHOR
with a junction table BOOK_AUTHOR
).
SelectConditionStep<Record1<String>> query = create
.select(AUTHOR.LASTNAME.as("AuthorName"))
.from(
(
BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
)
.where(BOOK.TITLE.eq(CLRS_title))
;
匹配整本 table 效率有点低,只匹配 select 一本书。我现在想在比赛前 select 那本书。
The jOOQ doc on this matter 让我相信它看起来像这样:
Table<Record1<Integer>> clrs = create
.select(BOOK.ID.as("bookID"))
.from(BOOK)
.where(BOOK.TITLE.eq(CLRS_title))
.asTable()
;
SelectJoinStep<Record1<String>> query = create
.select(AUTHOR.LASTNAME.as("AuthorName"))
.from(
(
clrs.leftOuterJoin(BOOK_AUTHOR).on(clrs.field("bookID").eq(BOOK_AUTHOR.BOOKID))
).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
)
;
但是,编译失败,因为
Cannot resolve method 'eq(org.jooq.TableField<ch.cypherk.bookdb.public_.tables.records.BookAuthorRecord,java.lang.Integer>)'
在加入条件中。
这个连接的正确写法是什么?
您遇到的问题
您正在使用 Table.field(String)
:
从派生的 table 中取消引用列
clrs.field("bookID")
您返回的类型是 Field<?>
,带有通配符。与任何泛型类型一样,一旦你有了通配符,很多操作(但不是全部)将不再可能在该类型上进行。以List<?>
为例。您仍然可以调用 List<?>.get()
来检索 Object
,但不能调用 List<?>.add(? element)
。在 Field<?>
中,您不能再调用 eq()
,除非您将参数转换为原始类型。
您还可以将字段的 <T>
类型强制转换为您已知的类型,例如通过使用 Table.field(String, DataType<T>)
clrs.field("bookID", BOOK.ID.getDataType())
研究各种选项,您可能会发现最有用的选项
更好地解决您的查询
你真的不需要
- 将您的子查询分配给局部变量
- 使用派生的 table 解决您的问题
通常使用 jOOQ,如果您遇到上述派生 table 的问题,问问自己真的没有我可以写的更简单的查询吗?
你真正需要的是semi join。写:
// Assuming this static import
import static org.jooq.impl.DSL.*;
ctx.select(AUTHOR.LASTNAME)
.from(AUTHOR)
.where(AUTHOR.ID.in(
select(BOOK_AUTHOR.AUTHORID)
.from(BOOK_AUTHOR)
.join(BOOK).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
.where(BOOK.TITLE.eq(clrsTitle))
)
.fetch();
假设我想找出谁在一本书 db 中写了 CLRS
(tables BOOK
, AUTHOR
with a junction table BOOK_AUTHOR
).
SelectConditionStep<Record1<String>> query = create
.select(AUTHOR.LASTNAME.as("AuthorName"))
.from(
(
BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
)
.where(BOOK.TITLE.eq(CLRS_title))
;
匹配整本 table 效率有点低,只匹配 select 一本书。我现在想在比赛前 select 那本书。
The jOOQ doc on this matter 让我相信它看起来像这样:
Table<Record1<Integer>> clrs = create
.select(BOOK.ID.as("bookID"))
.from(BOOK)
.where(BOOK.TITLE.eq(CLRS_title))
.asTable()
;
SelectJoinStep<Record1<String>> query = create
.select(AUTHOR.LASTNAME.as("AuthorName"))
.from(
(
clrs.leftOuterJoin(BOOK_AUTHOR).on(clrs.field("bookID").eq(BOOK_AUTHOR.BOOKID))
).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
)
;
但是,编译失败,因为
Cannot resolve method 'eq(org.jooq.TableField<ch.cypherk.bookdb.public_.tables.records.BookAuthorRecord,java.lang.Integer>)'
在加入条件中。
这个连接的正确写法是什么?
您遇到的问题
您正在使用 Table.field(String)
:
clrs.field("bookID")
您返回的类型是 Field<?>
,带有通配符。与任何泛型类型一样,一旦你有了通配符,很多操作(但不是全部)将不再可能在该类型上进行。以List<?>
为例。您仍然可以调用 List<?>.get()
来检索 Object
,但不能调用 List<?>.add(? element)
。在 Field<?>
中,您不能再调用 eq()
,除非您将参数转换为原始类型。
您还可以将字段的 <T>
类型强制转换为您已知的类型,例如通过使用 Table.field(String, DataType<T>)
clrs.field("bookID", BOOK.ID.getDataType())
研究各种选项,您可能会发现最有用的选项
更好地解决您的查询
你真的不需要
- 将您的子查询分配给局部变量
- 使用派生的 table 解决您的问题
通常使用 jOOQ,如果您遇到上述派生 table 的问题,问问自己真的没有我可以写的更简单的查询吗?
你真正需要的是semi join。写:
// Assuming this static import
import static org.jooq.impl.DSL.*;
ctx.select(AUTHOR.LASTNAME)
.from(AUTHOR)
.where(AUTHOR.ID.in(
select(BOOK_AUTHOR.AUTHORID)
.from(BOOK_AUTHOR)
.join(BOOK).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
.where(BOOK.TITLE.eq(clrsTitle))
)
.fetch();