jOOQ - 在查询中简明地表示列和聚合/窗口函数

时间:2014-08-14 17:03:17

标签: java postgresql jooq

这篇帖子是我在类似问题上留下的评论的结果:https://stackoverflow.com/a/19860271/2308858

我正在使用PostgreSQL和jOOQ 3.4并尝试在jOOQ中表示以下SQL查询:

SELECT *, COUNT(*) OVER() 
FROM table1 t1
JOIN table2 t2 ON (t1.id = t2.id)
JOIN table3 t3 ON (t1.otherId = t3.otherId)

我喜欢Postgres如何让我简洁地代表“所有列加上count列”只有SELECT *, COUNT(*) OVER()。但是当我尝试在jOOQ中表示相同的查询时,我能做的最简洁的方法是:

create.select( TABLE1.fields() ).select( TABLE2.fields() ).select( TABLE3.fields() ).select( count().over() )
   .from( TABLE1 )
   .join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
   .join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))

理想情况下,我会写这个:

create.select().select( count().over() )
   .from( TABLE1 )
   .join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
   .join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))

但这似乎不起作用。有关如何做到这一点的任何想法?

1 个答案:

答案 0 :(得分:5)

您自己发现的这个解决方案确实是采用jOOQ API的方法:

create.select( TABLE1.fields() )
      .select( TABLE2.fields() )
      .select( TABLE3.fields() )
      .select( count().over() )
      ...

它在概念上对应于此有效的SQL查询:

SELECT table1.*, table2.*, table3.*, COUNT(*) OVER()
...

操纵jOOQ"模型API":

但如果这对你来说很烦人,你也可以用这个小技巧解决这个问题:

// Get access to the "model API" from a statement without any SELECT fields
SelectQuery<?> select =
create.select()
      .from( TABLE1 )
      .join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
      .join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
      .getQuery();

// Copy all fields from the SELECT statement:
List<Field<?>> fields = new ArrayList<>(select.getSelect());

// And explicitly add them:
select.addSelect(fields);
select.addSelect(count().over());

这与您最初的尝试同样冗长,但通常可能更简单一些。

使用派生表

当然,您也可以简单地编写以下等效SQL查询,这将是更标准的SQL:

SELECT t.*, COUNT(*) OVER()
FROM (
  SELECT *
  FROM table1 t1
  JOIN table2 t2 ON (t1.id = t2.id)
  JOIN table3 t3 ON (t1.otherId = t3.otherId)
) t

使用jOOQ,这将转换为:

Table<?> t = select()
            .from( TABLE1 )
            .join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
            .join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
            .asTable("t");

create.select(t.fields(), count().over())
      .from(t);

支持星号

在jOOQ的未来版本the actual asterisk (*) might be supported explicitly through the jOOQ API中。在这一点上,有些不清楚如何在句法上实现这一点。

在旁注:

我总是发现PostgreSQL在这里允许这种语法非常好奇:

SELECT *, COUNT(*) OVER() 
...

SQL引擎几乎没有支持它,并且有点不可预测&#34;。 SQL标准也不允许使用#34;独立的星号&#34;与其他列表达式结合使用。