问题:
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/
答案 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)
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