【发布时间】:2020-04-03 21:53:42
【问题描述】:
使用 jOOQ 3.11.2 和 Postgres 9.4,我试图在第二个 CTE 的定义中重新使用一个 jOOQ CTE。
以下每个 StackOverflow 问题 How to re-use one CTE in another CTE in jOOQ 不正确
CommonTableExpression<...> cteTwo = name().fields().as(select( with(cteOne ... ).from(cteOne) );
基于上述答案,我完全省略了 cteTwo 中的 with(cteOne) 子句。我试过了:
import static org.jooq.impl.DSL.*;
CommonTableExpression<...> cteOne = name().fields().as(select(...);
CommonTableExpression<...> cteTwo = name().fields().as(select().from(cteOne) ); // seem to need with(cteOne) here.
List<someDTO> result = create
.with(cteOne)
.with(CteTwo)
.select(...)
.from(cteTwo)
.fetchInto(someDTO.class);
上面编译但运行时出现错误:'jooq: bad SQL grammar。 ...错误:关系“cteOne”不存在。查看生成的 SQL,cteTwo 中没有对 cteOne 的引用。
然后我尝试将with(cteOne) 子句放在 cteTwo 定义内的不同位置。在 SELECT 子句之前只有三个地方可以尝试。没有一个是正确的:
CommonTableExpression<...> cteTwo = with(cteOne).name().fields().as(select( ... ).from(cteOne) );
CommonTableExpression<...> cteTwo = name() with(cteOne).fields().as(select( ... ).from(cteOne) );
CommonTableExpression<...> cteTwo = name().fields().with(cteOne).as(select( ... ).from(cteOne) );
请注意,这不同于定义多个 CTE,然后在最终的 select 语句中使用每个 CTE,如下所示:
CommonTableExpression<...> cteAlpha = name(...).fields(...).as(select(...);
CommonTableExpression<...> cteBeta = name(...).fields(...).as(select(...);
List<SomeDTO> list = create
.with(cteAlpha)
.with(cteBeta)
.select(...) from(cteAlpha, cteBeta).fetchInto(SomeDTO.class);
我还没有找到涵盖这一点的文档或示例。 这应该怎么做?
【问题讨论】:
-
@LukasEder 我发现一种解决方法是将 CTE 的结果保存为临时表。虽然是两刃剑。使结果更容易可视化,但会使数据库变得混乱,并且需要额外的内务处理才能删除临时文件。我仍然很想知道上述问题是否有答案。
-
也许这不是一个更可取的解决方案,但内联 CTE 会是另一种解决方法吗?我的意思是如果“b”需要从“a”中选择,那么必须设置“b”将从与“a”相同的确切定义中选择,而不是从临时名称“a”中选择”。如果有多个嵌套级别,这将变得非常麻烦,但我想我会问
-
感谢您的建议 - 这可能有效,但我认为它首先违背了定义 CTE 的目的。使用临时数据库表作为解决方法也是一种代码味道。最后,我从树上退下来,看着树林。更大的问题是验证从许多不同办公室手动输入的摘要报告是否已完整记录。我发现在现有报告图表中添加另一个图表系列线并让用户直观地进行验证要简单得多。我最终没有在这个解决方案中使用 jOOQ。
标签: java sql common-table-expression jooq