如何仅在一个事务中计算Jooq / SQL中一列的百分比?

时间:2018-08-15 17:25:35

标签: sql jooq

问题:

Grades Table
---------------
Name    Score 
"Bob"     "A"
"Sally"   "A"
"Joe"     "B"
"Ann"     "C"

假设我有此表,并且我想计算出有C的学生百分比。正确的答案是25%。如何在JOOQ中的一项交易中执行此操作(如果需要,还可以使用原始SQL)?还是不可能?谢谢。

错误的解决方案:两笔交易:

float numberOfC = database.fetchCountOfStudentsWithGrade("C");  //Transaction
float numberOfStudents = database.fetchCountOfStudents(); //Transaction
float percentage = numberOfC / numberOfStudents;

良好的解决方案尝试:一次交易-JOOQ

context.select(val(context.selectCount().from(TABLE1))
          .div(val(context.selectCount().from(TABLE1))))  // This line has error
          .fetch(0, int.class); //One transaction

//Error: Cannot resolve method `div(org.jooq.Param<T>)`

算术表达式的Jooq文档:

https://www.jooq.org/doc/latest/manual/sql-building/column-expressions/arithmetic-expressions/

2 个答案:

答案 0 :(得分:2)

在原始sql中,您可以执行以下操作:

select avg(case when score = 'C' then 1.0 else 0 end) as c_ratio
from t;

以上是标准语法,应在所有数据库中运行。在某些数据库中,您可以这样写:

select avg( score = 'C' ) as c_ratio
from t;

答案 1 :(得分:0)

使用SQL标准FILTER (WHERE ..)

jOOQ中的一种选择是像这样使用AggregateFunction.filterWhere()

ctx.select(count().filterWhere(T.SCORE.eq("C"))
                  .cast(BigDecimal.class)
                  .div(count()))
   .from(T)
   .fetch();

以上假设以下静态导入:

import static org.jooq.impl.DSL.*;

HSQLDB和PostgreSQL对COUNT(*) FILTER (WHERE x)语法具有本机支持。在所有其他数据库中,jOOQ将使用COUNT(CASE WHEN x THEN 1 END)对此进行仿真。

有关相关子查询的方法的说明

在您的问题中,您建议了一种使用相关子查询进行COUNT(*)计算的方法。如果有solution running several aggregations in one step

,运行几个这样的子查询几乎从来不是一个好主意。