[#600] Add support for Oracle / SQL Standard linear regression functions
This commit is contained in:
parent
7f3e0fb63d
commit
eeaa60bee8
@ -40,6 +40,7 @@ import static org.jooq.tools.reflect.Reflect.on;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
@ -696,6 +697,17 @@ public abstract class BaseTest<
|
||||
catch (InterruptedException ignore) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Round all strings to a given scale, to avoid annoying floating point side-effects
|
||||
*/
|
||||
protected static String[] roundStrings(int n, String... strings) {
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
strings[i] = "" + new BigDecimal(strings[i]).setScale(n, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to create a new dummy book
|
||||
*/
|
||||
|
||||
@ -69,6 +69,15 @@ import static org.jooq.impl.Factory.minDistinct;
|
||||
import static org.jooq.impl.Factory.ntile;
|
||||
import static org.jooq.impl.Factory.percentRank;
|
||||
import static org.jooq.impl.Factory.rank;
|
||||
import static org.jooq.impl.Factory.regrAvgX;
|
||||
import static org.jooq.impl.Factory.regrAvgY;
|
||||
import static org.jooq.impl.Factory.regrCount;
|
||||
import static org.jooq.impl.Factory.regrIntercept;
|
||||
import static org.jooq.impl.Factory.regrR2;
|
||||
import static org.jooq.impl.Factory.regrSXX;
|
||||
import static org.jooq.impl.Factory.regrSXY;
|
||||
import static org.jooq.impl.Factory.regrSYY;
|
||||
import static org.jooq.impl.Factory.regrSlope;
|
||||
import static org.jooq.impl.Factory.rowNumber;
|
||||
import static org.jooq.impl.Factory.stddevPop;
|
||||
import static org.jooq.impl.Factory.stddevSamp;
|
||||
@ -79,6 +88,7 @@ import static org.jooq.impl.Factory.varPop;
|
||||
import static org.jooq.impl.Factory.varSamp;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Field;
|
||||
@ -278,6 +288,68 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinearRegressionFunctions() throws Exception {
|
||||
switch (getDialect()) {
|
||||
case CUBRID:
|
||||
case DERBY:
|
||||
case FIREBIRD:
|
||||
case H2:
|
||||
case HSQLDB:
|
||||
case INGRES:
|
||||
case MYSQL:
|
||||
case SQLITE:
|
||||
case SQLSERVER:
|
||||
log.info("SKIPPING", "Skipping linear regression function tests");
|
||||
return;
|
||||
}
|
||||
|
||||
// [#600] As aggregate functions
|
||||
Record record =
|
||||
create().select(
|
||||
regrAvgX(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrAvgY(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrCount(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrIntercept(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrR2(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrSlope(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrSXX(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrSXY(TBook_ID(), TBook_AUTHOR_ID()),
|
||||
regrSYY(TBook_ID(), TBook_AUTHOR_ID()))
|
||||
.from(TBook())
|
||||
.fetchOne();
|
||||
|
||||
List<String> values = Arrays.asList("1.5", "2.5", "4.0", "-0.5", "0.8", "2.0", "1.0", "2.0", "5.0");
|
||||
assertEquals(values, Arrays.asList(roundStrings(1, record.into(String[].class))));
|
||||
|
||||
switch (getDialect()) {
|
||||
case DB2:
|
||||
log.info("SKIPPING", "Skipping linear regression window function tests");
|
||||
return;
|
||||
}
|
||||
|
||||
// [#600] As window functions
|
||||
Result<Record> result =
|
||||
create().select(
|
||||
regrAvgX(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrAvgY(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrCount(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrIntercept(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrR2(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrSlope(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrSXX(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrSXY(TBook_ID(), TBook_AUTHOR_ID()).over(),
|
||||
regrSYY(TBook_ID(), TBook_AUTHOR_ID()).over())
|
||||
.from(TBook())
|
||||
.orderBy(TBook_ID())
|
||||
.fetch();
|
||||
|
||||
assertEquals(values, Arrays.asList(roundStrings(1, result.get(0).into(String[].class))));
|
||||
assertEquals(values, Arrays.asList(roundStrings(1, result.get(1).into(String[].class))));
|
||||
assertEquals(values, Arrays.asList(roundStrings(1, result.get(2).into(String[].class))));
|
||||
assertEquals(values, Arrays.asList(roundStrings(1, result.get(3).into(String[].class))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWindowFunctions() throws Exception {
|
||||
switch (getDialect()) {
|
||||
|
||||
@ -1371,6 +1371,16 @@ public abstract class jOOQAbstractTest<
|
||||
new AggregateWindowFunctionTests(this).testAggregateFunctions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountDistinct() throws Exception {
|
||||
new AggregateWindowFunctionTests(this).testCountDistinct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinearRegressionFunctions() throws Exception {
|
||||
new AggregateWindowFunctionTests(this).testLinearRegressionFunctions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListAgg() throws Exception {
|
||||
new AggregateWindowFunctionTests(this).testListAgg();
|
||||
|
||||
@ -5129,13 +5129,6 @@ public class Factory implements FactoryOperations {
|
||||
|
||||
/**
|
||||
* Get the median over a numeric field: median(field)
|
||||
* <p>
|
||||
* This is known to be supported in any of these RDBMS:
|
||||
* <ul>
|
||||
* <li>HSQLDB</li>
|
||||
* <li>Oracle</li>
|
||||
* <li>Sybase SQL Anywhere</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Support({ HSQLDB, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> median(Field<? extends Number> field) {
|
||||
@ -5144,20 +5137,6 @@ public class Factory implements FactoryOperations {
|
||||
|
||||
/**
|
||||
* Get the population standard deviation of a numeric field: stddev_pop(field)
|
||||
* <p>
|
||||
* This is known to be supported in any of these RDBMS:
|
||||
* <ul>
|
||||
* <li>DB2</li>
|
||||
* <li>H2</li>
|
||||
* <li>HSQLDB</li>
|
||||
* <li>Ingres</li>
|
||||
* <li>MySQL</li>
|
||||
* <li>Oracle</li>
|
||||
* <li>Postgres</li>
|
||||
* <li>SQL Server (stdev)</li>
|
||||
* <li>Sybase ASE</li>
|
||||
* <li>Sybase SQL Anywhere</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Support({ ASE, CUBRID, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> stddevPop(Field<? extends Number> field) {
|
||||
@ -5166,20 +5145,6 @@ public class Factory implements FactoryOperations {
|
||||
|
||||
/**
|
||||
* Get the sample standard deviation of a numeric field: stddev_samp(field)
|
||||
* <p>
|
||||
* This is known to be supported in any of these RDBMS:
|
||||
* <ul>
|
||||
* <li>DB2</li>
|
||||
* <li>H2</li>
|
||||
* <li>HSQLDB</li>
|
||||
* <li>Ingres</li>
|
||||
* <li>MySQL</li>
|
||||
* <li>Oracle</li>
|
||||
* <li>Postgres</li>
|
||||
* <li>SQL Server (stdev)</li>
|
||||
* <li>Sybase ASE</li>
|
||||
* <li>Sybase SQL Anywhere</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Support({ ASE, CUBRID, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> stddevSamp(Field<? extends Number> field) {
|
||||
@ -5188,20 +5153,6 @@ public class Factory implements FactoryOperations {
|
||||
|
||||
/**
|
||||
* Get the population variance of a numeric field: var_pop(field)
|
||||
* <p>
|
||||
* This is known to be supported in any of these RDBMS:
|
||||
* <ul>
|
||||
* <li>DB2</li>
|
||||
* <li>H2</li>
|
||||
* <li>HSQLDB</li>
|
||||
* <li>Ingres</li>
|
||||
* <li>MySQL</li>
|
||||
* <li>Oracle</li>
|
||||
* <li>Postgres</li>
|
||||
* <li>SQL Server (stdev)</li>
|
||||
* <li>Sybase ASE</li>
|
||||
* <li>Sybase SQL Anywhere</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Support({ ASE, CUBRID, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> varPop(Field<? extends Number> field) {
|
||||
@ -5210,24 +5161,147 @@ public class Factory implements FactoryOperations {
|
||||
|
||||
/**
|
||||
* Get the sample variance of a numeric field: var_samp(field)
|
||||
* <p>
|
||||
* This is known to be supported in any of these RDBMS:
|
||||
* <ul>
|
||||
* <li>H2</li>
|
||||
* <li>HSQLDB</li>
|
||||
* <li>Ingres</li>
|
||||
* <li>MySQL</li>
|
||||
* <li>Oracle</li>
|
||||
* <li>Postgres</li>
|
||||
* <li>SQL Server (var)</li>
|
||||
* <li>Sybase SQL Anywhere</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Support({ ASE, CUBRID, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> varSamp(Field<? extends Number> field) {
|
||||
return new Function<BigDecimal>(Term.VAR_SAMP, SQLDataType.NUMERIC, nullSafe(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_SLOPE</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrSlope(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_slope", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_INTERCEPT</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrIntercept(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_intercept", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_COUNT</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrCount(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_count", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_R2</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrR2(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_r2", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_AVGX</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrAvgX(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_avgx", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_AVGY</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrAvgY(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_avgy", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_SXX</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrSXX(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_sxx", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_SYY</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrSYY(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_syy", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>REGR_SXY</code> linear regression function
|
||||
* <p>
|
||||
* The linear regression functions fit an ordinary-least-squares regression
|
||||
* line to a set of number pairs. You can use them as both aggregate and
|
||||
* window functions, where this is supported.
|
||||
* <p>
|
||||
* Note that {@link SQLDialect#DB2} does not support linear regression
|
||||
* window functions.
|
||||
*/
|
||||
@Support({ DB2, POSTGRES, ORACLE, SYBASE })
|
||||
public static AggregateFunction<BigDecimal> regrSXY(Field<? extends Number> y, Field<? extends Number> x) {
|
||||
return new Function<BigDecimal>("regr_sxy", SQLDataType.NUMERIC, nullSafe(y), nullSafe(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the aggregated concatenation for a field.
|
||||
* <p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user