英文:
How to write nested sql query in jooq with SUM operation in SELECT
问题
我有一个嵌套的SQL查询,我想在jOOQ中编写该查询。
以下是如何在jOOQ中实现这个查询的示例:
import static org.jooq.impl.DSL.*;
import org.jooq.*;
import org.jooq.impl.*;
public class JooqExample {
public static void main(String[] args) {
// 创建一个DSLContext(取决于你的数据库类型)
DSLContext context = DSL.using(SQLDialect.YOUR_SQL_DIALECT);
// 创建子查询
Field<Integer> successCount = sum(field(name("api_status")).eq("COMPLETED")).as("success_count");
Field<Integer> failureCount = sum(field(name("api_status")).notEqual("COMPLETED")).as("failure_count");
Field<Integer> totalCount = countDistinct(field(name("transaction_id"))).as("total");
Select<Record4<Integer, String, String, Integer>> subquery = context.select(
field(name("master_id", Integer.class)),
field(name("transaction_id", String.class)),
field(name("api_status", String.class)),
field(name("organisation_name", String.class))
)
.from(table(name("test_master_table")))
.leftJoin(table(name("organisation_table")))
.on(field(name("test_master_table", "organisation_id", Integer.class))
.eq(field(name("organisation_table", "organisation_id", Integer.class))))
.leftJoin(table(name("upload_table")))
.on(field(name("test_master_table", "master_id", Integer.class))
.eq(field(name("upload_table", "master_id", Integer.class)))
.where(field(name("organisation_id", Integer.class)).eq(1)
.and(field(name("created_date")).ge(currentTimestamp()))
.groupBy(field(name("test_master_table", "master_id", Integer.class)));
// 在主查询中使用子查询
Result<Record4<Integer, String, String, Integer>> result = context.select(
field(name("organisation_name", String.class)),
successCount,
failureCount,
totalCount
)
.from(subquery)
.fetch();
// 输出结果
System.out.println(result);
}
}
请注意,你需要将 YOUR_SQL_DIALECT
替换为你实际使用的数据库的SQL方言,以及根据你的表和字段名称修改上面的代码。此示例仅演示如何将给定的SQL查询转换为jOOQ查询。
英文:
I have a nested sql query and I want to write that query in jooq.
select organisation_name, sum(api_status = 'COMPLETED') as success_count, sum(api_status <> 'COMPLETED') as failure_count, count(distinct transaction_id) as 'total'
from (
select test_master_table.master_id, test_master_table.transaction_id, test_master_table.api_status, organsiations_table.organisation_name
from test_master_table
left join organsiations_table on test_master_table.organisation_id = organsiations_table.organisation_id
left join upload_table on test_master_table.master_id = upload_table.master_id
where (test_master_table.organisation_id = '1' AND (created_date >= current_timestamp()))
group by test_master_table.master_id) as test;
How can this be done in JOOQ?
Here is the sample SQL query which can be used to replicate the desired output.If executed the given query below with the table data attached, the nested query provide a different result than the one suggested(query for which has been attached as well).
CREATE TABLE test_master_table (
master_id INTEGER PRIMARY KEY,
transaction_id TEXT NOT NULL,
api_status TEXT,
organsiation_id INTEGER Not NULL
);
CREATE TABLE organisation_table (
organsiation_id INTEGER not NULL,
organisation_name TEXT not null
);
CREATE TABLE upload_table (
master_id INTEGER NOT NULL,
statement_id TEXT PRIMARY KEY,
file_status TEXT,
type TEXT
);
INSERT INTO test_master_table values (1, 'txn-1', 'ERROR', 1);
INSERT INTO test_master_table values(2, 'txn-2', 'ERROR', 1);
INSERT INTO test_master_table values (3, 'txn-3', 'COMPLETED', 1);
INSERT INTO test_master_table values (4, 'txn-4', 'COMPLETED', 1);
INSERT INTO organisation_table values (1,'org-1');
INSERT INTO organisation_table values (2,'org-2');
INSERT INTO organisation_table values (3,'org-3');
INSERT INTO upload_table values (1, 'stmt-1', 'COMPLETED', 'type-1');
INSERT INTO upload_table values (1, 'stmt-2', 'COMPLETED', 'type-1');
INSERT INTO upload_table values (1, 'stmt-3', 'COMPLETED', 'type-1');
INSERT INTO upload_table values (2, 'stmt-4', 'COMPLETED', 'type-1');
INSERT INTO upload_table values (2, 'stmt-5', 'COMPLETED', 'type-1');
INSERT INTO upload_table values (2, 'stmt-6', 'COMPLETED', 'type-1');
-- Query to get the desired output
select organisation_name, sum(api_status = 'COMPLETED') as successCount, sum(api_status <> 'COMPLETED') as failureCount, count(distinct master_id)
from (
select test_master_table.master_id, test_master_table.transaction_id, test_master_table.api_status, organisation_table.organisation_name
from test_master_table
left join organisation_table on test_master_table.organsiation_id = organisation_table.organsiation_id
left join upload_table on test_master_table.master_id = upload_table.master_id
where organisation_table.organsiation_id = '1' and type = 'type-1'
group by test_master_table.master_id
) as test;
-- Query suggested (does not reproduce the desired result)
/*select organisation_table.organisation_name, sum(api_status = 'COMPLETED') as successCount, sum(api_status <> 'COMPLETED') as failureCount, count(distinct test_master_table.master_id)
from test_master_table
left join organisation_table on test_master_table.organsiation_id = organisation_table.organsiation_id
left join upload_table on test_master_table.master_id = upload_table.master_id
where organisation_table.organsiation_id = '1' and type = 'type-1'
group by test_master_table.master_id;*/
答案1
得分: 1
简化查询首先
您的特定查询不需要派生表。我会将它重写成这样:
select
organisation_name,
sum(api_status = 'COMPLETED') as success_count,
sum(api_status <> 'COMPLETED') as failure_count,
count(distinct transaction_id) as 'total'
from test_master_table
left join organsiations_table
on test_master_table.organisation_id = organsiations_table.organisation_id
left join upload_table
on test_master_table.master_id = upload_table.master_id
left join request_table
on test_master_table.request_id = request_table.id
where (test_master_table.organisation_id = '1'
and (created_date >= current_timestamp())
group by test_master_table.master_id;
从语义上来说,您不会失去任何东西,而且更容易转换为 jOOQ。这是一个常见的话题。很多时候,当人们在 jOOQ 中创建派生表时遇到困难,问题可以通过这种方式来解决。如此频繁,以至于我决定在 jOOQ 博客上写一篇关于这个的博文。
将派生表转换为 jOOQ
jOOQ 手册关于派生表的部分展示了如何做。您首先必须将派生表分配给本地变量:
Table<?> nested = select(...).from(...).groupBy(...).asTable("nested");
然后从中解引用列,例如:
// 如果您的字段是一个表达式:
nested.field("field_name");
// 如果您的字段来自生成的代码,在这种情况下
// 列是按名称匹配的:
nested.field(TABLE.COLUMN);
如何具体执行
我知道您有一个更具体的问题。我会在那里解释具体的问题。
英文:
Simplifying the query first
Your particular query doesn't require a derived table. I'd rewrite it to this:
select
organisation_name,
sum(api_status = 'COMPLETED') as success_count,
sum(api_status <> 'COMPLETED') as failure_count,
count(distinct transaction_id) as 'total'
from test_master_table
left join organsiations_table
on test_master_table.organisation_id = organsiations_table.organisation_id
left join upload_table
on test_master_table.master_id = upload_table.master_id
left join request_table
on test_master_table.request_id = request_table.id
where (test_master_table.organisation_id = '1'
and (created_date >= current_timestamp())
group by test_master_table.master_id;
You'll lose absolutely nothing in terms of semantics, and it will be easier to translate to jOOQ. This is a frequent topic. A lot of times when people struggle creating derived tables in jOOQ, the problem could be circumvented this way. So frequent, I decided to write a blog post about this on the jOOQ blog.
Translating derived tables to jOOQ
The jOOQ manual section about derived tables shows how to do it. You have to assign the derived table to a local variable first:
Table<?> nested = select(...).from(...).groupBy(...).asTable("nested");
And then dereference columns from it, e.g.:
// If your field is an expression:
nested.field("field_name");
// If your field is from generated code, in case of which
// columns are matched by name:
nested.field(TABLE.COLUMN);
How to do it specifically
I'm aware you have a more specific question about this. I'll explain the specific problem there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论