我尝试实现一对多关系中一方的偏移分页和多方过滤,并通过窗口函数计算总数。
由于笛卡尔积的问题,我得到了指定的球颜色过滤器值的不正确的盒子总数:
Map<Integer, List<Box>> result = ctx.selectDistinct(
Box.asterisk(), count().over().as("total"))
.from(BOX)
.leftJoin(BALL).on(BALL.BOX_ID.eq(BOX.ID))
.where(BALL.COLOR.eq("red"))
.orderBy(BOX.BOX_ID)
.limit(size)
.offset(size * page)
.fetchGroups(field("total", Integer.class), record-{ mapping logic in dto });
我尝试用countDistinct重写jooq查询:
Map<Integer, List<Box>> result = ctx.selectDistinct(
Box.asterisk(), countDistinct(BOX.ID).over().as("total"))
.from(BOX)
.leftJoin(BALL).on(BALL.BOX_ID.eq(BOX.ID))
.where(BALL.COLOR.eq("red"))
.orderBy(BOX.BOX_ID)
.limit(size)
.offset(size * page)
.fetchGroups(field("total", Integer.class), record-{ mapping logic in projection});
并获取:org.postgresql.util.PSQLException:错误:窗口函数未实现DISTINCT
请帮助,我不想写2个单独的jooq查询,以获得总计数和页面。
我想消除重复的单一jooq查询的结果集,并使其正确的全球数量的可用框记录与红球通过一个1选择数据库端的最有效的方法。
1条答案
按热度按时间krugob8w1#
您只投影
BOX
列,使用BALL
连接只计算每个盒子的红球。因此,只需使用GROUP BY
即可(要知道,DISTINCT
的大多数用法可能不是最佳的):几点意见:
GROUP BY
一个主键,并且仍然投影所有功能相关的列。I've blogged about it here。如果您没有使用PostgreSQL,那么只需列出GROUP BY
中的所有BOX.fields()
。BALL.COLOR.eq("red")
predicate 移到了LEFT JOIN
的ON
子句see also this blog post I wrote that explains it中。简而言之,如果将该 predicate 留在WHERE
子句中,则会将LEFT JOIN
变成INNER JOIN
,这是您不希望看到的。请注意,在这种情况下,您不能再使用COUNT(*)
,而是COUNT(BALL.ID)
,以获得BOX
es的0
计数,而没有BALL
s(而不是1
计数)。