[英]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")));
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 . 在其他数据库中,还有其他方法可以实现此目的,请参见此处的本文 。
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. 如果您从任何表中以无类型名称(
String
或org.jooq.Name
)访问字段,则编译器没有任何类型信息可放入结果Field<?>
,这就是为什么原始代码无法编译的原因。
You can, however, use one of the following techniques: 但是,您可以使用以下技术之一:
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)));
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)));
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.