jOOQ join选择<! - ? - >对象

时间:2018-06-14 06:57:16

标签: java mysql sql jooq

我想在SQL中执行类似的操作:

SELECT 
  * 
FROM 
  tbl1 t1 
  INNER JOIN 
  (SELECT MAX(col1) as maxCol, col2 FROM tbl1 t1 GROUP BY t1.col2) subQ
  ON t1.col2 = subQ.col2
  AND t1.col1 = subQ.maxCol

在jOOQ中,我将subQ存储到Select<?>对象中:

Select<?> subQ = myDSL.select(DSL.max(TBL1.COL1).as("maxCol"), TBL1.COL2)
                      .from(TBL1)
                      .groupBy(TBL1.COL2);

我的问题是,如何从maxCol获取subQ列并在join中使用它?我的join是这样的:

select()
.from(TBL1)
.join(subQ.asTable())
.on(TBL1.COL1.eq(subQ.asTable().field("maxCol")));

我在.on()

上有错误
  

类型字段中的方法eq(String)不适用于参数(字段)

我该怎么办?

2 个答案:

答案 0 :(得分:0)

这解决了问题:

select().from(TBL1).join(subQ.asTable()).on(TBL1.COL1.eq((Field<DataType>) subQ.field("maxCol")));

答案 1 :(得分:0)

使用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版本

如果您从任何表中按无类型名称(Stringorg.jooq.Name)访问字段,则编译器没有任何类型信息可以放在生成的Field<?>上,这是为什么你的原始代码没有编译。

但是,您可以使用以下技术之一:

请记住原始的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)));

maxCol

之后为您的TBL1.COL1列命名

在这个特定的用例中,可能不会引入任何新名称,而是重用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)));