简体   繁体   English

JOOQ 多选计数与 PostgreSQL 一次连接

[英]JOOQ multiple select count in one connection with PostgreSQL

I have a table SUBSCRIPTION , I want to run multiple selectCount written with JOOQ in one connection with different predicates to the database.我有一个表SUBSCRIPTION ,我想在一个连接中运行多个用selectCount编写的selectCount与数据库的不同谓词。 To do so, I have created a list of queries:为此,我创建了一个查询列表:

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

And finally, I have launched this list of queries using batch :最后,我使用batch启动了这个查询列表:

using(configuration).batch(countQueries).execute();

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.我希望在execute的返回值中有上述查询的结果,但我得到一个填充了0值的整数数组。

Is this the right way to run multiple selectCount using JOOQ?这是使用 JOOQ 运行多个selectCount的正确方法吗? What is the signification of the integer array returned by the execute method? execute方法返回的整数数组的意义是什么?

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.我在 JOOQ 博客中检查了这个链接,谈论“如何在单个查询中计算多个聚合函数”,但它只是关于 SQL 查询,没有 JOOQ 方言。

Comments on your assumptions对你的假设的评论

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

The batch() API can only be used for DML queries ( INSERT , UPDATE , DELETE ), just like with native JDBC. batch() API 只能用于 DML 查询( INSERTUPDATEDELETE ),就像原生 JDBC 一样。 I mean, you can run the queries as a batch, but you cannot fetch the results this way.我的意思是,您可以批量运行查询,但不能以这种方式获取结果。

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.我在 JOOQ 博客中检查了这个链接,谈论“如何在单个查询中计算多个聚合函数”,但它只是关于 SQL 查询,没有 JOOQ 方言。

Plain SQL queries almost always translate quite literally to jOOQ, so you can apply the technique from that article also in your case.普通 SQL 查询几乎总是从字面上转换为 jOOQ,因此您也可以在您的案例中应用该文章中的技术。 In fact, you should!事实上,你应该! Running so many queries is definitely not a good idea.运行这么多查询绝对不是一个好主意。

Translating that linked query to jOOQ将该链接查询翻译为 jOOQ

So, let's look at how to translate that plain SQL example from the link to your case:因此,让我们看看如何将简单的 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();

This will produce a single record containing all the count values.这将生成包含所有计数值的单个记录。

As always, this is assuming the following static import与往常一样,这是假设以下静态导入

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

Using classic GROUP BY使用经典的GROUP BY

Of course, you can also just use a classic GROUP BY in your particular case.当然,您也可以在特定情况下使用经典的GROUP BY This might even be a bit faster:这甚至可能更快一点:

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

This now produces a table with one count value per code.现在生成一个表,每个代码有一个计数值。 Alternatively, fetch this into a Map<String, Integer> :或者,将其提取到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());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM