使用 MySQL 8.0
如果您使用的是 MySQL 8.0+,请不要使用子查询,而是使用窗口函数。这将是您的等效查询:
SELECT *
FROM (
SELECT t1.*, RANK() OVER (PARTITION BY t1.col2 ORDER BY col1 DESC) rk
FROM tbl1 t1
) t
WHERE t.rk = 1
优点是您只有一个tbl1 访问权限,这可能会运行得更快。
This is often also called a TOP-n query. In other databases, there are other ways to implement this, see this article here.
使用旧的 MySQL 版本
如果您从任何表中通过未键入的名称(String 或 org.jooq.Name)访问字段,则编译器没有任何类型信息可用于生成的 Field<?>,这就是为什么您的原始代码没有t 编译。
但是,您可以使用以下技术之一:
记住原来的maxCol字段引用
从您的子查询中,取出 maxCol 字段引用并将其分配给一个局部变量(假设它的类型为 Integer,如果需要,请替换):
Field<Integer> maxCol = DSL.max(TBL1.COL1).as("maxCol");
Select<?> subQ = myDSL.select(maxCol, TBL1.COL2).from(TBL1).groupBy(TBL1.COL2);
现在,您还可以使用此引用从子查询中提取列:
Field<Integer> subQMaxCol = subQ.field(maxCol);
或直接在您的解决方案中内联:
select().from(TBL1)
.join(subQ.asTable())
.on(TBL1.COL1.eq(subQ.field(maxCol)));
以TBL1.COL1 命名您的maxCol 列
在这个特定的用例中,不引入任何新名称可能有意义,而是重新使用 COL1 作为名称:
Select<?> subQ = myDSL.select(DSL.max(TBL1.COL1).as(TBL1.COL1), TBL1.COL2)
.from(TBL1)
.groupBy(TBL1.COL2);
在这种情况下(如果没有不明确的 COL1 列名),您可以使用该引用再次从子查询中提取 COL1 字段:
select().from(TBL1)
.join(subQ.asTable())
.on(TBL1.COL1.eq(subQ.field(TBL1.COL1)));
使用TBL1.COL1 引用的数据类型
从您的原始解决方案中,只需在从子查询中提取字段时添加数据类型:
select().from(TBL1)
.join(subQ.asTable())
.on(TBL1.COL1.eq(subQ.field("maxCol", TBL1.COL1.getDataType())));
或者,强制它:
select().from(TBL1)
.join(subQ.asTable())
.on(TBL1.COL1.eq(subQ.field("maxCol").coerce(TBL1.COL1)));