[#5939] Add PRODUCT() aggregate and window function
This commit is contained in:
parent
f43dfec59a
commit
97d652e08b
@ -17360,6 +17360,36 @@ public class DSL {
|
||||
return new org.jooq.impl.Function<BigDecimal>("sum", true, SQLDataType.NUMERIC, nullSafe(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product over a numeric field: product(field).
|
||||
* <p>
|
||||
* No database currently supports multiplicative aggregation natively. jOOQ
|
||||
* emulates this using <code>exp(sum(log(arg)))</code> for strictly positive
|
||||
* numbers, and does some additional handling for zero and negative numbers.
|
||||
* <p>
|
||||
* More information here: <a href=
|
||||
* "https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql">https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql</a>.
|
||||
*/
|
||||
@Support
|
||||
public static AggregateFunction<BigDecimal> product(Field<? extends Number> field) {
|
||||
return new org.jooq.impl.Function<BigDecimal>(Term.PRODUCT, SQLDataType.NUMERIC, nullSafe(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sum over a numeric field: product(distinct field).
|
||||
* <p>
|
||||
* No database currently supports multiplicative aggregation natively. jOOQ
|
||||
* emulates this using <code>exp(sum(log(arg)))</code> for strictly positive
|
||||
* numbers, and does some additional handling for zero and negative numbers.
|
||||
* <p>
|
||||
* More information here: <a href=
|
||||
* "https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql">https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql</a>.
|
||||
*/
|
||||
@Support
|
||||
public static AggregateFunction<BigDecimal> productDistinct(Field<? extends Number> field) {
|
||||
return new org.jooq.impl.Function<BigDecimal>(Term.PRODUCT, true, SQLDataType.NUMERIC, nullSafe(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average over a numeric field: avg(field).
|
||||
*/
|
||||
|
||||
@ -53,10 +53,13 @@ import static org.jooq.SQLDialect.POSTGRES_9_4;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
import static org.jooq.impl.DSL.condition;
|
||||
import static org.jooq.impl.DSL.inline;
|
||||
import static org.jooq.impl.DSL.mode;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DSL.one;
|
||||
import static org.jooq.impl.DSL.percentileCont;
|
||||
import static org.jooq.impl.DSL.when;
|
||||
import static org.jooq.impl.DSL.zero;
|
||||
import static org.jooq.impl.Keywords.K_AS;
|
||||
import static org.jooq.impl.Keywords.K_DENSE_RANK;
|
||||
import static org.jooq.impl.Keywords.K_DISTINCT;
|
||||
@ -78,6 +81,7 @@ import static org.jooq.impl.Term.ARRAY_AGG;
|
||||
import static org.jooq.impl.Term.LIST_AGG;
|
||||
import static org.jooq.impl.Term.MEDIAN;
|
||||
import static org.jooq.impl.Term.MODE;
|
||||
import static org.jooq.impl.Term.PRODUCT;
|
||||
import static org.jooq.impl.Term.ROW_NUMBER;
|
||||
import static org.jooq.impl.Tools.DataKey.DATA_WINDOW_DEFINITIONS;
|
||||
|
||||
@ -237,6 +241,40 @@ class Function<T> extends AbstractField<T> implements
|
||||
|
||||
ctx.visit(percentileCont(new BigDecimal("0.5")).withinGroupOrderBy(fields));
|
||||
}
|
||||
else if (term == PRODUCT) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
Field<Integer> f = (Field) DSL.field("{0}", arguments.get(0));
|
||||
Field<Integer> negatives = DSL.when(f.lt(zero()), inline(-1));
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
Field<BigDecimal> negativesSum = new CustomField<BigDecimal>("sum", SQLDataType.NUMERIC) {
|
||||
@Override
|
||||
public void accept(Context<?> c) {
|
||||
c.visit(distinct
|
||||
? DSL.sumDistinct(negatives)
|
||||
: DSL.sum(negatives));
|
||||
|
||||
toSQLFilterClause(c);
|
||||
toSQLOverClause(c);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
Field<BigDecimal> logarithmsSum = new CustomField<BigDecimal>("sum", SQLDataType.NUMERIC) {
|
||||
@Override
|
||||
public void accept(Context<?> c) {
|
||||
c.visit(DSL.sum(DSL.ln(DSL.abs(f))));
|
||||
|
||||
toSQLFilterClause(c);
|
||||
toSQLOverClause(c);
|
||||
}
|
||||
};
|
||||
|
||||
ctx.visit(
|
||||
when(negativesSum.mod(inline(2)).lt(inline(BigDecimal.ZERO)), inline(-1))
|
||||
.otherwise(one()).mul(DSL.exp(logarithmsSum))
|
||||
);
|
||||
}
|
||||
else {
|
||||
toSQLArguments(ctx);
|
||||
toSQLKeepDenseRankOrderByClause(ctx);
|
||||
|
||||
@ -214,6 +214,12 @@ enum Term {
|
||||
return "octet_length";
|
||||
}
|
||||
},
|
||||
PRODUCT {
|
||||
@Override
|
||||
public String translate(SQLDialect dialect) {
|
||||
return "product";
|
||||
}
|
||||
},
|
||||
ROW_NUMBER {
|
||||
@Override
|
||||
public String translate(SQLDialect dialect) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user