【问题标题】:How to get the first result from a group (Jooq)如何从组中获得第一个结果(Jooq)
【发布时间】:2020-08-22 03:59:09
【问题描述】:

我的要求是获取标识符列表,每个标识符可以引用多条记录,并返回每个标识符的最新记录。

这似乎可以通过标识符列上的orderBy(date, desc)fetchGroups() 的组合来实现。然后我使用values() 来获取 Result 对象。

此时,我想要每个结果对象中的第一个值。我可以通过get(0) 获得列表中的第一个值,但这似乎是作弊。有没有更好的方法从 Result 对象中获取第一个结果?

【问题讨论】:

  • 提供样本数据、所需结果和数据库标签。

标签: java sql orm jooq


【解决方案1】:

您将编写一个 top-1-per-category 查询,这是 top-n-per-category query 的一个特例。 jOOQ 也支持在 SQL 中产生这种行为的大多数语法。您不应该在客户端使用分组,因为您会将所有多余的数据从服务器传输到客户端,这对应于每个组的剩余结果。

一些例子:

标准 SQL(当支持窗口函数时)

Field<Integer> rn = rowNumber().over(T.DATE.desc()).as("rn");

var subquery = table(
    select(T.fields())
   .select(rn)
   .from(T)
).as("subquery");

var results = 
ctx.select(subquery.fields(T.fields())
   .from(subquery)
   .where(subquery.field(rn).eq(1))
   .fetch();

Teradata 和 H2 (we might emulate this soon)

var results = 
ctx.select(T.fields())
   .from(T)
   .qualify(rowNumber().over(T.DATE.desc()).eq(1))
   .fetch();

PostgreSQL

var results = 
ctx.select(T.fields())
   .distinctOn(T.DATE)
   .from(T)
   .orderBy(T.DATE.desc())
   .fetch();

甲骨文

var results = 
ctx.select(
      T.DATE, 
      max(T.COL1).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COL1),
      max(T.COL2).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COL2),
      ...
      max(T.COLN).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COLN))
   .from(T)
   .groupBy(T.DATE)
   .fetch();

【讨论】:

  • 假设对于任何给定的组,只有 2-3 个可能的条目。你还是觉得窗口查询更胜一筹,还是 fetchGroups() 方法在那个时候更容易理解?
  • @JasonB:你问我是否更喜欢 SQL 方法? :-)
  • 感谢你所做的一切,卢卡斯! :-)
  • QUALIFY 值得 RDBMS 更多地采用 :)
  • @LukaszSzozda:完全同意!我们最终会支持在 jOOQ 中模拟它,但首先需要一些内部基础设施来支持它。
猜你喜欢
  • 2014-10-12
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多