【问题标题】:JOOQ multiple select count in one connection with PostgreSQL与 PostgreSQL 的一次连接中的 JOOQ 多选计数
【发布时间】:2021-01-09 21:09:27
【问题描述】:

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

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 的返回值中包含上述查询的结果,但我得到了一个用0 值填充的整数数组。

这是使用 JOOQ 运行多个 selectCount 的正确方法吗? execute方法返回的整数数组的含义是什么?

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

【问题讨论】:

    标签: java sql postgresql jooq


    【解决方案1】:

    对您的假设的评论

    我希望在执行的返回值中有上述查询的结果,但我得到了一个用 0 值填充的整数数组。

    batch() API 只能用于 DML 查询(INSERTUPDATEDELETE),就像使用原生 JDBC 一样。我的意思是,您可以批量运行查询,但不能以这种方式获取结果。

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

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

    将链接的查询转换为 jOOQ

    那么,让我们看看如何将简单的 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();
    

    现在这会生成一个表格,每个代码都有一个计数值。或者,将其提取到Map&lt;String, Integer&gt;

    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());
    

    【讨论】:

      猜你喜欢
      • 2016-08-13
      • 2018-06-05
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2017-07-29
      • 2020-09-15
      • 2019-11-20
      • 1970-01-01
      相关资源
      最近更新 更多