jOOQ - 加入嵌套子查询

Use*_*291 5 java sql nested-query jooq

假设我想找出谁写CLRS了一本书 db (tables BOOK, AUTHORwith ajunction 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))
        ;
Run Code Online (Sandbox Code Playgroud)

匹配整个表格有点低效,只是选择一本书。我现在想在比赛前选择那本书。

关于这个问题的 jOOQ 文档让我相信这可能看起来像这样:

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))
            )
        ;
Run Code Online (Sandbox Code Playgroud)

但是,这无法编译,因为

Cannot resolve method 'eq(org.jooq.TableField<ch.cypherk.bookdb.public_.tables.records.BookAuthorRecord,java.lang.Integer>)'
Run Code Online (Sandbox Code Playgroud)

在加入条件下。

编写此连接的正确方法是什么?

Luk*_*der 8

你遇到的问题

您正在使用以下方法取消对派生表中的列的引用Table.field(String)

clrs.field("bookID")
Run Code Online (Sandbox Code Playgroud)

您返回的类型是Field<?>,带有通配符。与任何泛型类型一样,一旦有了通配符,该类型将无法再进行许多操作(但不是全部)。以List<?>为例。您仍然可以调用List<?>.get()来检索Object,但不能List<?>.add(? element)。在 中Field<?>,您不能再调用eq(),除非您将参数转换为原始类型。

您还可以将您的字段<T>类型强制为您已经知道的类型,例如使用Table.field(String, DataType<T>)

clrs.field("bookID", BOOK.ID.getDataType())
Run Code Online (Sandbox Code Playgroud)

研究您的各种选项,您可能会发现最有用的选项

更好的解决您的查询

你真的不需要

  1. 将您的子查询分配给局部变量
  2. 使用派生表解决您的问题

通常使用 jOOQ,如果您在使用上述派生表时遇到问题,请问自己是否真的没有我可以编写的更简单的查询?

您真正需要的是半连接。写:

// 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();
Run Code Online (Sandbox Code Playgroud)

  • 我很感激您帮助提问者找到更简单的方法来解决他们的问题。我的查询不能以这种方式简化。您介意为他们原来的问题提供一个解决方案吗?我需要加入嵌套子选择的多列结果。我搜索了大约一个小时才找到答案。我在 JOOQ 博客上找到了几篇有关嵌套子查询和非常短的文档页面的文章,但没有一篇包含完整的可用示例。 (5认同)