jOOQ - 加入嵌套子查询

Posted

技术标签:

【中文标题】jOOQ - 加入嵌套子查询【英文标题】:jOOQ - join with nested subquery 【发布时间】:2019-08-09 20:11:27 【问题描述】:

假设我想找出谁在一本书的数据库中写了CLRS(表BOOKAUTHOR 和连接表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))
        ;

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

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>)'

在连接条件下。

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

【问题讨论】:

【参考方案1】:

你遇到的问题

您正在使用 Table.field(String) 取消引用派生表中的列:

clrs.field("bookID")

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

您还可以将字段的 &lt;T&gt; 类型强制为您已知的类型,例如通过使用Table.field(String, DataType&lt;T&gt;)

clrs.field("bookID", BOOK.ID.getDataType())

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

更好的查询解决方案

你真的不需要

    将子查询分配给局部变量 为您的问题使用派生表

经常使用 jOOQ,如果您在使用上述派生表时遇到问题,请问自己真的没有更简单的查询可以代替吗?

您真正需要的是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();

【讨论】:

感谢您帮助提问者找到了一种更简单的方法来解决他们的问题。我的查询不能以这种方式简化。您介意为他们最初的问题提供解决方案吗?我需要加入嵌套子选择的多列结果。我已经搜索了大约一个小时的答案。我在 JOOQ 博客上找到了几篇关于嵌套子查询和非常短的文档页面的文章,但没有一篇包含完整的可用示例。 @M.Leonhard:我很乐意回答你自己的具体问题,而不是编辑这个答案

以上是关于jOOQ - 加入嵌套子查询的主要内容,如果未能解决你的问题,请参考以下文章

求SQL相关子查询和嵌套子查询通俗的区别 ?

SQL相关子查询和嵌套子查询的区别

相关子查询 与 嵌套子查询 有何区别 ?

关于SQL DELETE嵌套子查询问题

SQL Server 之 子查询与嵌套查询

Qt怎样设置QMainWindow窗口中嵌套的QWidget子窗口的背景色