我正在尝试在JOOQ中表达以下SQL。但是,我要么在使用派生表的类型方面遇到了很多问题,要么得到了可以编译的内容,但是在SQL级别甚至在JAVA中都失败了。谁能给我一个想法,在这种情况下如何正确使用派生表?
SELECT
id,
ROUND(num_realized / num_requirements, 2) AS realized_percent,
ROUND(num_requirements / max_req, 2) AS activity_percent
FROM (
SELECT
requirement.project_id AS id,
COUNT(requirement.id) AS num_requirements,
COUNT(requirement.realized) AS num_realized
FROM
requirement
GROUP BY
requirement.project_id) AS stats
CROSS JOIN (
SELECT
MAX(num_requirements) AS max_req
FROM (
SELECT
requirement.project_id AS id,
COUNT(requirement.id) AS num_requirements,
COUNT(requirement.realized) AS num_realized
FROM
requirement
GROUP BY
requirement.project_id) AS stats) AS req_max
该语句在SQL中应用时效果很好,但我无法将此表达式放入JOOQ。
我最近的尝试是使用
Table<Record3<Integer, Integer, Integer>> stats =
DSL.select(
REQUIREMENT.PROJECT_ID.as("id"),
DSL.count(REQUIREMENT.ID).as("num_requirements"),
DSL.count(REQUIREMENT.REALIZED).as("num_realized")
).from(REQUIREMENT).groupBy(REQUIREMENT.PROJECT_ID).asTable("stats");
Table<Record2<Integer, Integer>> req_max =
DSL.select(
stats.field(0),
DSL.min(stats.field(1))
)
.from(stats).asTable("req_max");
但是我遇到错误:不兼容的类型:
Table<Record2<CAP#1,CAP#2>> cannot be converted to Table<Record2<Integer,Integer>>
我尝试了很多不同的技术,包括定义数据类型和使用.field(String,Datatype)而不是使用“ Records”,但是无论我做什么,它要么无法编译,要么在执行未知错误时失败。
我很乐意提供帮助。
通常,应尽可能避免自我联接。在许多情况下,与嵌套查询中的聚合相比,窗口函数可以解决问题得多。如果您使用的是MySQL 8,则查询可以重写为:
SELECT
requirement.project_id AS id,
ROUND(COUNT(requirement.realized) / COUNT(requirement.id), 2) AS realized_percent,
ROUND(COUNT(requirement.id) / MAX(COUNT(requirement.id)) OVER(), 2) AS activity_percent
FROM
requirement
GROUP BY
requirement.project_id
注意MAX(..) OVER()
window function, which can aggregate ordinary aggregation functions as explained here。我知道您使用的是MySQL 5.7,但尚不支持窗口功能,但出于完整性考虑,此答案需要基于窗口功能的解决方案-可能是出于升级动机:-)
首先可以通过简化基础SQL查询来简化许多复杂的jOOQ查询。
问题是您使用stats.field(0)
和stats.field(0)
。方法签名是
stats.field(1)
当按索引访问表的列时,jOOQ不可能为您提供类型安全,因此返回类型为Field<?> field(int index)
,其中列类型为通用通配符。这里有一些解决方案:
Field<?>
。仅从您的示例来看,我不确定此处是否需要任何类型安全性将字段引用提取为局部变量。而不是例如嵌入Table<?> req_max
表中的id
列,为什么不这样做:
stats
然后像这样使用它:
Field<Integer> id = REQUIREMENT.PROJECT_ID.as("id");
Field<Integer> numRequirements = DSL.count(REQUIREMENT.ID).as("num_requirements");
Field<Integer> numRealized = DSL.count(REQUIREMENT.REALIZED).as("num_realized");