【问题标题】:jOOQ - Return tuple of fields from "then" in "when" queryjOOQ - 在“when”查询中从“then”返回字段元组
【发布时间】:2019-11-24 07:56:33
【问题描述】:

我将 jOOQ 与 PostgreSQL 一起使用,并尝试使用 CASE WHEN 创建具有多个计数的选择查询。因为只计算唯一记录很重要,所以我也使用DISTINCT 语句。有时我需要区分多个列,这在 SQL 语法中是完全正确的,但我不知道如何在 jOOQ 中做到这一点。

我使用CASE 进行计数,因为我还有更多条件的查询。为了方便起见,我简化了这些示例。

工作 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

当我尝试只使用一个字段时,它可以工作:

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

但是当我尝试这样的事情时:

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

我收到以下错误:

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

我尝试了DSL.row(),因为我看到IN 语句的类似用法。我也尝试用DSL.select() 替换它,但它不起作用,数组和列表都不起作用。

现在我通过编写一个小函数解决了这个问题:

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

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

但如果知道如何使用 jOOQ 的 API 来做到这一点,那就太好了。

【问题讨论】:

    标签: java sql postgresql jooq


    【解决方案1】:

    可以使用实验性的DSL.rowField() 方法将行值表达式(例如org.jooq.Row2)转换为普通列表达式(org.jooq.Field)。

    这将在 API 中工作,并可能生成适当的预期 SQL,但从 jOOQ 3.11 / 3.12 开始,此支持仍处于试验阶段,尚未经过良好测试。很可能是行字段在用于 CASE 等表达式时,将无法从数据库中正确获取。

    【讨论】:

      【解决方案2】:

      SQL 起作用的原因是因为("CategoryID", "PageID") 被解释为一个元组,Postgres 可以清楚地计算它们。否则,count(distinct) 不会接受多个表达式。

      我不知道如何在 JOOQ 中创建元组。但是,您可能可以进行一些字符串连接以生成 "CategoryID" || ':' || "PageID" 并获得您想要的结果。

      【讨论】:

      • 我知道我可以在 jOOQ 中使用纯 SQL,但我想尽可能避免这种情况。我以为DSL.row() 创建了元组,但显然DSL.when() 不想接受它作为一个字段。
      猜你喜欢
      • 2021-09-13
      • 1970-01-01
      • 2021-11-02
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多