JOOQ, 当连接多个表时,在'on子句'中的未知列'想法_service.parent_section.id'。

问题描述 投票:0回答:1

所以,我有五个表,我想在一个查询中取回它们。

parent_section(id, gate_id)


Assessment_Question(id,parent_section_id)


Assessment_question_multi_choice_option(id, question_id)


Assessment_answer_Group(id, entity_id)


Assessment_Answer(id,assessment_question_id, assessment_answer_Group_id)

我想列出所有的问题

错误是 Unknown column 'ideas_service.parent_section.id' in 'on clause'

以下是我的疑问

        dsl.select()
        .from(PARENT_SECTION,ASSESSMENT_ANSWER_GROUP)
        .join(ASSESSMENT_QUESTION)
        .on(PARENT_SECTION.ID.eq(ASSESSMENT_QUESTION.PARENT_SECTION_ID))
        .leftJoin(ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION)
        .on(
            ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION.ASSESSMENT_QUESTION_ID.eq(
                ASSESSMENT_QUESTION.ID))
        .join(ASSESSMENT_ANSWER)
        .on(ASSESSMENT_ANSWER_GROUP.ID.eq(ASSESSMENT_ANSWER.ASSESSMENT_ANSWER_GROUP_ID))
        .where(PARENT_SECTION.GATE_ID.eq(gateId))
        .fetch()

以前当我只想查询表的三个表,parent_Section_assessment_question和assessment_question_multi_choice的时候,我的查询是这样的,而且成功了。

    var queryResult =
    dsl.select()
        .from(PARENT_SECTION)
        .join(ASSESSMENT_QUESTION)
        .on(PARENT_SECTION.ID.eq(ASSESSMENT_QUESTION.PARENT_SECTION_ID))
        .leftJoin(ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION)
        .on(
            ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION.ASSESSMENT_QUESTION_ID.eq(
                ASSESSMENT_QUESTION.ID))
        .where(PARENT_SECTION.GATE_ID.eq(gateId))
        .fetch()

我应该如何修改工作查询,使之也能列出一个联接问题上的assessment_Answer_Group( where assessment_answer_Group.entity_id = x) 之间的assessment_answer.answer_group_id。

澄清一下加盟结构

我在parent_section和assessment_Question之间做了一个内部连接,在assessment_question和assessment_multi_choice_option之间做了一个左连接。

answer_group和assessment_answer之间的连接是独立于这三个表的,应该是assessment_answer_group.entity_id = x,并且连接到assessment_Answer.answer_Group_id = assessment_answer_Grorup.id。

edit: 在akinas的评论之后,我的查询现在是这样的,它找到了assessment_answer_group,但是没有找到任何assessment_answers。

    var queryResult =
    dsl.select()
      //below line is cross join with an always true join coniditon
        .from(PARENT_SECTION.join(ASSESSMENT_ANSWER_GROUP).on(true))
        .join(ASSESSMENT_QUESTION)
        .on(PARENT_SECTION.ID.eq(ASSESSMENT_QUESTION.PARENT_SECTION_ID))
        .leftJoin(ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION)
        .on(
            ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION.ASSESSMENT_QUESTION_ID.eq(
                ASSESSMENT_QUESTION.ID))
        .join(ASSESSMENT_ANSWER)
        .on(ASSESSMENT_ANSWER_GROUP.ID.eq(ASSESSMENT_ANSWER.ASSESSMENT_ANSWER_GROUP_ID))
        .where(PARENT_SECTION.GATE_ID.eq(gateId))
mysql jooq
1个回答
0
投票

为什么会出现语法错误

你得到这个错误的原因。

错误的原因是在 "on子句 "中,未知列 "its_service.parent_section.id"。

是因为你要加入 ASSESSMENT_QUESTIONASSESSMENT_ANSWER_GROUP,不要 PARENT_SECTION 在你的jOOQ查询中。

dsl.select()
   .from(PARENT_SECTION,ASSESSMENT_ANSWER_GROUP)
   .join(ASSESSMENT_QUESTION)
   .on(PARENT_SECTION.ID.eq(ASSESSMENT_QUESTION.PARENT_SECTION_ID))
   // ...

就像其他人在评论中指出的那样 你把逗号和列表分开的语法和ANSI JOIN语法混在一起了。无论是在 SQL 中,还是在 jOOQ 中,几乎都不推荐这样做。在jOOQ中,你上面的查询对应于这个SQL。

SELECT *
FROM PARENT_SECTION, (
  ASSESSMENT_ANSWER_GROUP 
    JOIN ASSESSMENT_QUESTION 
      ON PARENT_SECTION.ID = ASSESSMENT_QUESTION.PARENT_ID
  )
..

正如你所看到的,连接表达式没有任何意义 因为你在使用一个谓词连接两张表,而这个谓词引用了一张不在范围内的表。我最近写了一篇博客文章,通过添加这样的括号,可能有助于理解SQL JOIN语法。. 我认为括号在这里绝对有帮助。

这是我对正确连接的建议。

  • 永远不要把表列表和ANSI联接混在一起,这通常只会带来麻烦(尽管在边缘情况下它可能很有用)。如果你需要外联接,你不能在大多数SQL方言中使用表列表(除了Oracle),所以你还是需要ANSI联接。坚持使用它们。
  • 小心将外联接和内联接混在一起。联接是操作符,而 要知道,他们的关联性很重要。

笛卡尔产品

但是你还有一个问题。在SQL中,你不能轻易地将几个对多关系连接起来,否则你会得到卡托式产品。的意思。

  • A PARENT_SECTION 可以有很多 ASSESSMENT_QUESTION,它可以有许多 ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION. 这是2个层次的to-many关系,将重复的 PARENT_SECTIONASSESSMENT_QUESTION 并再次 ASSESSMENT_QUESTIONASSESSMENT_QUESTION_MULTI_CHOICE_OPTION. 这种重复性的复制是可以的,因为你是在连接树的一个分支上进行的。
  • 然而,一个 ASSESSMENT_QUESTION 也有几个 ASSESSMENT_ANSWER因为那是另一种对多关系。这就造成了问题。

所以,你最终会得到一个cartesian product between ASSESSMENT_QUESTION_MULTI_CHOICE_OPTIONASSESSMENT_ANSWER因为你正在遍历连接树的两个独立的to-many分支,这绝对不是你想要的。

虽然你的5-join查询最终可能是正确的。句法上但还是会错 语义上!

得到它的权利

你将不得不 使用XMLJSON(从jOOQ 3.14开始)或运行(至少)2个查询。

// Query 1 producing ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION
dsl.select()
   .from(PARENT_SECTION)
   .join(ASSESSMENT_QUESTION)
     .on(ASSESSMENT_QUESTION.PARENT_SECTION_ID.eq(PARENT_SECTION.ID))
   .leftJoin(ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION)
     .on(ASSESSMENT_QUESTION_MULTI_CHOICE_OPTION.ASSESSMENT_QUESTION_ID
       .eq(ASSESSMENT_QUESTION.ID))
   .where(PARENT_SECTION.GATE_ID.eq(gateId))
   .fetch();

// Query 2 producing ASSESSMENT_ANSWER and ASSESSMENT_ANSWER_GROUP
dsl.select()
   .from(ASSESSMENT_ANSWER)
   .join(ASSESSMENT_ANSWER_GROUP)
     .on(ASSESSMENT_ANSWER_GROUP.ID.eq(ASSESSMENT_ANSWER.ASSESSMENT_ANSWER_GROUP_ID))
   .where(ASSESSMENT_ANSWER.ASSESSMENT_QUESTION_ID.in(
     select(ASSESSMENT_QUESTION.ID)
     .from(ASSESSMENT_QUESTION)
     .join(PARENT_SECTION)
     .on(ASSESSMENT_QUESTION.PARENT_SECTION_ID.eq(PARENT_SECTION.ID))
     .where(PARENT_SECTION.GATE_ID.eq(gateId))
   ))
   .fetch();

然后你可以在你的客户端中把结果组合在一起。注意第二个查询不需要加入 PARENT_SECTIONASSESSMENT_QUESTION 不再。A 半连接 (使用 IN 谓词)就可以了。

使用隐式连接

jOOQ支持一对一关系的隐式连接。. 上面的查询2也可以这样写,这可能更简单一些(尽管我建议你先研究一下 "真正的 "连接)。

dsl.select()
   .from(ASSESSMENT_ANSWER)
   .join(ASSESSMENT_ANSWER_GROUP)
     .on(ASSESSMENT_ANSWER_GROUP.ID.eq(ASSESSMENT_ANSWER.ASSESSMENT_ANSWER_GROUP_ID))
   .where(ASSESSMENT_ANSWER.assessmentQuestion().parentSection().GATE_ID.eq(gateId))
   .fetch();
© www.soinside.com 2019 - 2024. All rights reserved.