JOOQ multiple select count in one connection 与 PostgreSQL

JOOQ multiple select count in one connection with PostgreSQL

我有一个 table SUBSCRIPTION,我想 运行 多个 selectCount 用 JOOQ 在一个连接中用不同的谓词连接到数据库。 为此,我创建了一个查询列表:

List<Query> countQueries = channels.stream().map(c ->
                selectCount().from(SUBSCRIPTION)
                        .innerJoin(SENDER).on(SENDER.ID.equal(SUBSCRIPTION.SENDER_ID))
                        .innerJoin(CHANNEL).on(CHANNEL.ID.equal(SUBSCRIPTION.CHANNEL_ID))
                        .where(SENDER.CODE.equal(senderCode))
                        .and(CHANNEL.CODE.equal(c))
        ).collect(toList());

最后,我使用 batch:

启动了这个查询列表
using(configuration).batch(countQueries).execute();

我原本希望在 execute 的 return 值中得到上述查询的结果,但我得到了一个填充了 0 值的整数数组。

这是使用 JOOQ 运行 多个 selectCount 的正确方法吗? 用execute方法return得到的整型数组是什么意思?

我在 JOOQ 博客中查看了这个 link,谈论“如何在单个查询中计算多个聚合函数”,但它只是关于 SQL 查询,没有 JOOQ 方言。

对您的假设的评论

I have expected to have the results of the above queries in the return values of execute, but I get an array of integer filled with 0 values.

batch() API 只能用于 DML 查询(INSERTUPDATEDELETE),就像原生 [=44] =].我的意思是,您可以 运行 批量查询,但您无法通过这种方式获取结果。

I have checked this link, in the JOOQ blog, talking about "How to Calculate Multiple Aggregate Functions in a Single Query", but It's just about SQL queries, no JOOQ dialects.

普通 SQL 查询几乎总是按字面意思翻译成 jOOQ,因此您也可以在您的案例中应用那篇文章中的技术。事实上,你应该! 运行这么多查询肯定不是个好主意。

将 linked 查询翻译成 jOOQ

那么,让我们看看如何将 link 中的简单 SQL 示例翻译成您的案例:

Record record =
ctx.select(
      channels.stream()
              .map(c -> count().filterWhere(CHANNEL.CODE.equal(c)).as(c))
              .collect(toList())
   )
   .from(SUBSCRIPTION)
   .innerJoin(SENDER).on(SENDER.ID.equal(SUBSCRIPTION.SENDER_ID))
   .innerJoin(CHANNEL).on(CHANNEL.ID.equal(SUBSCRIPTION.CHANNEL_ID))
   .where(SENDER.CODE.equal(senderCode))
   .and(CHANNEL.CODE.in(channels)) // Not strictly necessary, but might speed up things
   .fetch();

这将生成包含所有计数值的单个记录。

一如既往,这是假设以下静态导入

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

使用经典 GROUP BY

当然,您也可以在特定情况下只使用经典 GROUP BY。这甚至可能会更快一些:

Result<?> result =
ctx.select(CHANNEL.CODE, count())
   .from(SUBSCRIPTION)
   .innerJoin(SENDER).on(SENDER.ID.equal(SUBSCRIPTION.SENDER_ID))
   .innerJoin(CHANNEL).on(CHANNEL.ID.equal(SUBSCRIPTION.CHANNEL_ID))
   .where(SENDER.CODE.equal(senderCode))
   .and(CHANNEL.CODE.in(channels)) // This time, you need to filter
   .groupBy(CHANNEL.CODE)
   .fetchOne();

这现在生成一个 table,每个代码有一个计数值。或者,将其提取到 Map<String, Integer>:

Map<String, Integer> map =
ctx.select(CHANNEL.CODE, count())
   .from(SUBSCRIPTION)
   .innerJoin(SENDER).on(SENDER.ID.equal(SUBSCRIPTION.SENDER_ID))
   .innerJoin(CHANNEL).on(CHANNEL.ID.equal(SUBSCRIPTION.CHANNEL_ID))
   .where(SENDER.CODE.equal(senderCode))
   .and(CHANNEL.CODE.in(channels))
   .groupBy(CHANNEL.CODE)
   .fetchMap(CHANNEL.CODE, count());