简体   繁体   English

jOOQ加入选择 <?> 宾语

[英]jOOQ join Select<?> object

I want to perform something like this in SQL: 我想在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

In jOOQ, I store the subQ into Select<?> object: 在jOOQ中,我将subQ存储到Select<?>对象中:

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

My question is, how to get the maxCol column from subQ and use it in join ? 我的问题是,如何从subQ获取maxCol列并在join使用它? My join is something like this: 我的join是这样的:

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

I have error on .on() 我在.on().on()

The method eq(String) in the type Field is not applicable for the arguments (Field) Field类型的eq(String)方法不适用于参数(Field)

what should I do? 我该怎么办?

这样可以解决问题:

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

Using MySQL 8.0 使用MySQL 8.0

If you're using MySQL 8.0+, don't use a subquery but a window function instead. 如果您使用的是MySQL 8.0+,请不要使用子查询,而要使用窗口函数。 This would be the equivalent query to yours: 这将是与您相同的查询:

SELECT *
FROM (
  SELECT t1.*, RANK() OVER (PARTITION BY t1.col2 ORDER BY col1 DESC) rk
  FROM tbl1 t1
) t
WHERE t.rk = 1

The advantage is that you only have a single tbl1 access, which is likely to run faster. 优点是您只有一个tbl1访问权限,这可能会运行得更快。

This is often also called a TOP-n query. 这通常也称为TOP-n查询。 In other databases, there are other ways to implement this, see this article here . 在其他数据库中,还有其他方法可以实现此目的,请参见此处的本文

Using older MySQL versions 使用旧的MySQL版本

If you access a field by untyped name ( String or org.jooq.Name ) from any table, then the compiler does not have any type information to put on the resulting Field<?> , which is why your original code doesn't compile. 如果您从任何表中以无类型名称( Stringorg.jooq.Name )访问字段,则编译器没有任何类型信息可放入结果Field<?> ,这就是为什么原始代码无法编译的原因。

You can, however, use one of the following techniques: 但是,您可以使用以下技术之一:

Remember the original maxCol field reference 记住原始的maxCol字段参考

From your subquery, factor out the maxCol field reference and assign it to a local variable (assuming it is of type Integer , replace if needed): 从子查询中,取出maxCol字段引用,并将其分配给局部变量(假设其类型为Integer ,如果需要,请替换):

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

Now, you can also use this reference to extract a column from the subquery: 现在,您还可以使用此引用从子查询中提取列:

Field<Integer> subQMaxCol = subQ.field(maxCol);

Or inline that directly in your solution: 或者直接在您的解决方案中内联:

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

Name your maxCol column after TBL1.COL1 TBL1.COL1命名您的maxCol

In this particular use-case, it might make sense not to introduce any new names, but to re-use COL1 as a name: 在此特定用例中,可能不引入任何新名称而是将COL1作为名称重新使用是有意义的:

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

In this case (if there is no ambiguous COL1 column name), you can use that reference to extract the COL1 field again from the subquery: 在这种情况下(如果没有不明确的COL1列名),则可以使用该引用再次从子查询中提取COL1字段:

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

Use the TBL1.COL1 reference's data type 使用TBL1.COL1参考的数据类型

From your original solution, just add the data type when you extract the field from the subquery: 从原始解决方案中,只需在从子查询中提取字段时添加数据类型:

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

Or, coerce it: 或者,强制:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM