jOOQ与Postgres的PERCENTILE_CONT和MEDIAN函数类型转换问题

huangapple go评论80阅读模式
英文:

jOOQ Postgres PERCENTILE_CONT & MEDIAN Issue with Type Casting

问题

Coercion of data types does not seem to work within median() or percentileCont(). Data type coercion works just fine with other aggregate functions like max() and min(). The Postgres queries that are produced as a result show that type casting is not applied in the final result.


MEDIAN

jOOQ Snippet

selectFields.add(
    median(
            field(String.format("%s.%s", a.getDataSourceName(), a.getField()))
                .coerce(Double.class)) // 似乎无法成功强制转换数据类型
        .as(
            String.format(
                "%s.%s.%s", a.getDataSourceName(), a.getField(), "median")));

SQL Output

select 
  tableA.columnA, 
  percentile_cont(0.5) within group (order by tableA.columnA) as "tableA.columnA.median" 
from tableA
group by tableA.columnA 
limit 100;

ERROR: function percentile_cont(numeric, text) does not exist


PERCENTILE_CONT

jOOQ Snippet

selectFields.add(
    percentileCont(a.getPercentileValue())
        .withinGroupOrderBy(
            field(String.format("%s.%s", a.getDataSourceName(), a.getField()))
                .coerce(Double.class)) // 似乎无法成功强制转换数据类型
        .as(
            String.format(
                "%s.%s.%s", a.getDataSourceName(), a.getField(), "percentile_" + Math.round(a.getPercentileValue() * 100))));

SQL Output

select 
  tableA.columnA, 
  percentile_cont(0.0) within group (order by tableA.columnA) as "tableA.columnA.percentile_0" 
from tableA.columnA
group by tableA.columnA
limit 100;

ERROR: function percentile_cont(numeric, text) does not exist


POSTGRES -- This works due to type casting

select 
	percentile_cont(0.5)
	within group (
		order by tableA.columnA::INTEGER
	)
	as "tableA.columnA.median" 
from tableA.columnA 
group by (select 1)

https://www.jooq.org/javadoc/latest/org.jooq/module-summary.html

英文:

Coercion of data types does not seem to work within median() or percentileCont(). Data type coercion works just fine with other aggregate functions like max() and min(). The Postgres queries that are produced as a result show that type casting is not applied in the final result. Below are the snippets from jOOQ and Postgres for reference. As of now, I have no work-around or knowledge of an open ticket for this issue.

Any direction would be much appreciated!


MEDIAN

jOOQ Snippet

selectFields.add(
    median(
            field(String.format("%s.%s", a.getDataSourceName(), a.getField()))
                .coerce(Double.class)) // Seems to not successfully coerce data types
        .as(
            String.format(
                "%s.%s.%s", a.getDataSourceName(), a.getField(), "median")));

SQL Output

select 
  tableA.columnA, 
  percentile_cont(0.5) within group (order by tableA.columnA) as "tableA.columnA.median" 
from tableA
group by tableA.columnA 
limit 100;

ERROR: function percentile_cont(numeric, text) does not exist


PERCENTILE_CONT

jOOQ Snippet

selectFields.add(
    percentileCont(a.getPercentileValue())
        .withinGroupOrderBy(
            field(String.format("%s.%s", a.getDataSourceName(), a.getField()))
                .coerce(Double.class)) // Seems to not successfully coerce data types
        .as(
            String.format(
                "%s.%s.%s", a.getDataSourceName(), a.getField(), "percentile_" + Math.round(a.getPercentileValue() * 100))));

SQL Output

select 
  tableA.columnA, 
  percentile_cont(0.0) within group (order by tableA.columnA) as "tableA.columnA.percentile_0" 
from tableA.columnA
group by tableA.columnA
limit 100;

ERROR: function percentile_cont(numeric, text) does not exist


POSTGRES -- This works due to type casting

select 
	percentile_cont(0.5)
	within group (
		order by tableA.columnA::INTEGER
	)
	as "tableA.columnA.median" 
from tableA.columnA 
group by (select 1)

https://www.jooq.org/javadoc/latest/org.jooq/module-summary.html

答案1

得分: 1

你并不在寻求强制转换,这在 jOOQ 中指的是仅在客户端更改数据类型,而不让服务器知道。这在从 jOOQ 产生某种其他数据类型(例如 BigInteger)的情况下,仍然对某种类型(例如 Integer)的数据进行获取时非常有用。请参阅关于 Field.coerce() 的 Javadoc。

> 与强制转换不同,强制转换不会影响数据库查看字段类型的方式。
>
> java
> // 这将一个 int 值绑定到 JDBC PreparedStatement
> DSL.val(1).coerce(String.class);
>
> // 这将一个 int 值绑定到 JDBC PreparedStatement
> // 并在 SQL 中将其强制转换为 VARCHAR
> DSL.val(1).cast(String.class);
>

很明显,你想要使用 Field.cast(),就像你的示例中实际使用了一个 cast tableA.columnA::INTEGER 一样。

英文:

You're not looking for coercion, which in jOOQ-speak means changing a data type only in the client without letting the server know. This is mostly useful when fetching data of some type (e.g. Integer) despite jOOQ producing some other data type (e.g. BigInteger), otherwise. See the Javadoc on Field.coerce()

> Unlike with casting, coercing doesn't affect the way the database sees a Field's type.
>
> java
> // This binds an int value to a JDBC PreparedStatement
> DSL.val(1).coerce(String.class);
>
> // This binds an int value to a JDBC PreparedStatement
> // and casts it to VARCHAR in SQL
> DSL.val(1).cast(String.class);
>

Cleary, you want to Field.cast(), instead, just like in your example where you actually used a cast tableA.columnA::INTEGER.

huangapple
  • 本文由 发表于 2020年4月9日 02:24:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/61107480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定