jOOQ聚合多个表

时间:2017-10-05 06:22:36

标签: sql aggregate-functions jooq

我们有一个存储记录的MAINTABLE。记录可以通过子表中的外键连接到CHILDTABLE1CHILDTABLE2内的子元素。

API允许从MAINTABLE接收对象列表。这些列表可以使用不同的策略进行排序,例如字母等。一种排序策略通过最新的子元素从MAINTABLE对对象进行排序。

例如:返回在这些项目中的最新事件(MAINTABLECHILDTABLE1)之后排序的项目(CHILDTABLE2)。

为此我想要一个具有CHILDTABLES最大值的字段。然后可以在"顺序中使用该字段。如果用户想要使用此排序策略,则来自MAINTABLE的语句。

点子:

// field with the highest creation date of any child element
Field<Object> maxDate = DSL.select(DSL.max(
                DSL.select(CHILDTABLE1.CREATION_DATE)
                .from(CHILDTABLE1)
                .where(CHILDTABLE1.FK.equal(MAINTABLE.ID))
                .asField()
                .union(
                   DSL.select(CHILDTABLE2.CREATION_DATE)
                  .from(CHILDTABLE2)
                  .where(CHILDTABLE1.FK.equal(MAINTABLE.ID))
                  .asField()
                )
        )).asField("maxDate");

// main query over MAINTABLE which orders by maxDate of any child element
List<Record> queryResults = jooq.select(*)
   .select(maxDate)
   .from(MAINTABLE)
   .orderBy(maxDate)
   .fetch();

此查询不起作用,因为无法计算maxDate。我想为maxDate创建一个新字段,以保持主要查询的整洁性,同时也因为&#34;顺序为&#34;声明将从另一种方法动态填充。此其他方法不知道主查询中新创建的字段,但可以访问maxDate字段。

任何建议都会很好。

1 个答案:

答案 0 :(得分:2)

让我们先看看如何使用SQL编写此查询。

根据我的理解,您希望从MAINTABLE中获取数据,这些数据按CHILDTABLE[N]中最新的相应条目排序。这可以按如下方式完成:

SELECT maintable.*
FROM maintable
JOIN (
  SELECT fk, max(creation_date) max_creation_date
  FROM (
    SELECT fk, creation_date
    FROM child_table1
    UNION ALL
    SELECT fk, creation_date
    FROM child_table2
  ) child_tables
  GROUP BY fk
) max_creation_dates
ON maintable.id = max_creation_dates.fk
ORDER BY max_creation_dates.max_creation_date DESC

当然,还有其他方法可以解决这个问题。您可以使用窗口函数或CROSS APPLY,具体取决于您的数据库。

将其翻译为jOOQ

这很容易。在jOOQ中,您可以在派生表存储在局部变量中,然后在“外部查询”中使用它们。我将重用与之前相同的名称:

Table<?> childTables = table(
   select(CHILD_TABLE1.FK, CHILD_TABLE1.CREATION_DATE)
  .from(CHILD_TABLE1)
  .unionAll(
   select(CHILD_TABLE2.FK, CHILD_TABLE2.CREATION_DATE)
  .from(CHILD_TABLE2)))
  .as("child_tables");

Table<?> maxCreationDates = table(
   select(
     childTables.field(CHILD_TABLE1.FK),
     max(childTables.field(CHILD_TABLE1.CREATION_DATE)).as("max_creation_date"))
  .from(childTables)
  .groupBy(childTables.field(CHILD_TABLE1.FK)))
  .as("max_creation_dates");

然后,您可以在实际查询中使用派生表:

using(configuration)
  .select(MAINTABLE.fields())
  .from(MAINTABLE)
  .join(maxCreationDates)
  .on(MAINTABLE.ID.eq(maxCreationDates.get(CHILD_TABLE1.FK)))
  .orderBy(maxCreationDates.get("max_creation_date").desc())
  .fetch();

以上暗示您拥有此静态导入:

import static org.jooq.impl.DSL.*;