简体   繁体   English

jOOQ - 从“when”查询中的“then”返回字段元组

[英]jOOQ - Return tuple of fields from "then" in "when" query

I use jOOQ with PostgreSQL and I'm trying to create a select query with multiple counts using CASE WHEN .我将 jOOQ 与 PostgreSQL 一起使用,并且我正在尝试使用CASE WHEN创建一个具有多个计数的选择查询。 Because it's important to count only unique records, I also use DISTINCT statement.因为只计算唯一记录很重要,所以我也使用DISTINCT语句。 Sometimes I need to distinct on multiple columns, which is perfectly correct in SQL syntax, but I can't figure out how to do it in jOOQ.有时我需要在多个列上进行区分,这在 SQL 语法中是完全正确的,但我不知道如何在 jOOQ 中做到这一点。

I use CASE for counting because I also have queries with more conditions.我使用CASE进行计数,因为我还有更多条件的查询。 I simplified these examples for convenience.为方便起见,我简化了这些示例。

Example working SQL:示例工作 SQL:

select
   count(distinct (case when "UserID" = 11 then "CategoryID" end)) as "UserCatNum",
   count(distinct (case when "UserID" = 11 then ("CategoryID", "PageID") end)) as "UserPageNum"
from data_table

When I try with just one field, it works:当我只尝试一个字段时,它有效:

query.addSelect(
    DSL.countDistinct(
        DSL.when(DSL.condition(Operator.AND, conditions), CATEGORY_ID)
    ).as("UserCatNum")
);

But when I try something like this:但是当我尝试这样的事情时:

query.addSelect(
    DSL.countDistinct(
        DSL.when(DSL.condition(Operator.AND, conditions),
        DSL.row(CATEGORY_ID, PAGE_ID))
    ).as("UserPageNum")
);

I'm getting the following error:我收到以下错误:

Cannot interpret argument of type class org.jooq.impl.RowImpl as a Field: ("data_table"."CategoryID", "data_table"."PageID")

I tried DSL.row() because I saw a similar usage with IN statements.我尝试了DSL.row()因为我看到了IN语句的类似用法。 I also tried replacing this with DSL.select() , but it doesn't work, neither Arrays and Lists.我也尝试用DSL.select()替换它,但它不起作用,数组和列表都不起作用。

For now I resolved this by writing a small function:现在我通过编写一个小函数解决了这个问题:

private Field<Object> tupleField(Field... fields) {
    String tuple = Arrays.stream(fields)
        .map(f -> f.getQualifiedName().quotedName().toString())
        .collect(Collectors.joining(","));

    return DSL.field("(" + tuple + ")");
}

But it would be nice to know how to do this using jOOQ's API.但是很高兴知道如何使用 jOOQ 的 API 来做到这一点。

A row value expression (eg org.jooq.Row2 ) can be converted to an ordinary column expression ( org.jooq.Field ) by using the experimental DSL.rowField() methods.可以使用实验性的DSL.rowField()方法将行值表达式(例如org.jooq.Row2 )转换为普通列表达式( org.jooq.Field )。

This will then work in the API, and might generate the appropriate expected SQL, but as of jOOQ 3.11 / 3.12, this support is still quite experimental and not well tested.这将在 API 中工作,并可能生成适当的预期 SQL,但从 jOOQ 3.11 / 3.12 开始,这种支持仍然是相当实验性的,没有经过很好的测试。 It might well be that row fields, when used in expressions like the CASE expression, will not be properly fetched from the database.很可能行字段在CASE表达式等表达式中使用时,将无法从数据库中正确获取。

The reason the SQL works is because ("CategoryID", "PageID") is interpreted as a tuple and Postgres can count those distinctly. SQL 工作的原因是因为("CategoryID", "PageID")被解释为一个元组并且 Postgres 可以清楚地计算这些。 Otherwise, count(distinct) does not take multiple expressions.否则, count(distinct)不会采用多个表达式。

I do not know how to create tuples in JOOQ.我不知道如何在 JOOQ 中创建元组。 However, you can probably do some string concatenation to result in "CategoryID" || ':' || "PageID"但是,您可能可以进行一些字符串连接以产生"CategoryID" || ':' || "PageID" "CategoryID" || ':' || "PageID" "CategoryID" || ':' || "PageID" and get the result you want. "CategoryID" || ':' || "PageID"并获得您想要的结果。

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

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