简体   繁体   English

按顺序排列的 jOOQ 子查询

[英]jOOQ Subquery in Order By

I'm using a subquery in order by like this on MySQL 8 database:我在 MySQL 8 数据库上按顺序使用子查询:

select * from series 
order by (select max(competition.competition_date) from competition 
          where competition.series_id = series.id) desc

But I didn't find a way to do that with jOOQ.但是我没有找到用 jOOQ 做到这一点的方法。

I tried the following query but this does not compile:我尝试了以下查询,但这无法编译:

dsl
   .selectFrom(SERIES)
   .orderBy(dsl.select(DSL.max(COMPETITION.COMPETITION_DATE))
               .from(COMPETITION).where(COMPETITION.SERIES_ID.eq(SERIES.ID)).desc())
   .fetch()

Are subqueries not supported in order by?按顺序不支持子查询吗?

Select<R> extends Field<R>

There's a pending feature request #4828 to let Select<R> extend Field<R> .有一个待处理的功能请求#4828Select<R> extend Field<R> This seems tempting because jOOQ already supports nested records to some extent for those dialects that support it.这似乎很诱人,因为对于那些支持它的方言,jOOQ 已经在某种程度上支持嵌套记录。

But I have some doubts whether this is really a good idea in this case, because no database I'm aware of (ie where I tried this) supports scalar subqueries that project more than one column.但是我怀疑在这种情况下这是否真的是一个好主意,因为我所知道的(即我在哪里尝试过的)没有数据库支持投影多个列的标量子查询。 It's possible to use such subqueries in row value expression predicates, eg可以在行值表达式谓词中使用这样的子查询,例如

(a, b) IN (SELECT x, y FROM t)

But that's a different story, because it's limited to predicates, and not arbitrary column expressions.但这是另一回事,因为它仅限于谓词,而不是任意列表达式。 And it is already supported in jOOQ, via the various DSL.row() overloads, eg jOOQ 已经通过各种DSL.row()重载支持它,例如

row(A, B).in(select(T.X, T.Y).from(T))

Select<Record1<T>> extends Field<T>

This is definitely desireable, because a SELECT statement that projects only one column of type T really is a Field<T> in SQL, ie a scalar subquery.这绝对是可取的,因为仅投影类型T的一列的SELECT语句实际上SQL 中的Field<T> ,即标量子查询。 But letting Select<Record1<T>> extend Field<T> is not possible in Java.但是让Select<Record1<T>>扩展Field<T>在 Java 中是不可能的。 There is no way to express this using Java's generics.无法使用 Java 的 generics 来表达这一点。 If we wanted to do this, we'd have to "overload" the Select type itself and create如果我们想这样做,我们必须“重载” Select类型本身并创建

  • Select1<T1> extends Select<Record1<T1>>
  • Select2<T1, T2> extends Select<Record2<T1, T2>>
  • etc.等等

In that case, Select1<T1> could be a special case, extending Field<T1> , and the other ones would not participate in such a type hierarchy.在这种情况下, Select1<T1>可能是一种特殊情况,扩展Field<T1> ,而其他的将不参与这种类型层次结构。 But in order to achieve this, we'd have to duplicate the entire Select DSL API per projection degree , ie copy it 22 times, which is probably not worth it.但是为了实现这一点,我们必须复制整个Select DSL API每个投影度,即复制 22 次,这可能不值得。 There are already 67 Select.*Step types in the jOOQ API , as of jOOQ 3.13.截至 jOOQ 3.13, jOOQ API 中已经有 67 个Select.*Step类型 This makes it difficult to justify the enhancement even only for scalar subqueries, ie for Select1 .这使得即使仅针对标量子查询(即Select1 )也很难证明增强的合理性。

Using DSL.field(Select<Record1<T>>) and related API使用DSL.field(Select<Record1<T>>)和相关的 API

You've already found the right answer .你已经找到了正确的答案 While Select<Record1<T>> cannot extend Field<T> , we can accept Select<? extends Record1<T>>虽然Select<Record1<T>>不能扩展Field<T> ,但我们可以接受Select<? extends Record1<T>> Select<? extends Record1<T>> in plenty of API, as an overload to the usual T|Field<T> overloads.在大量 API 中Select<? extends Record1<T>> ,作为对通常T|Field<T>重载的重载。 This has been done occasionally, and might be done more thoroughly throughout the API: https://github.com/jOOQ/jOOQ/issues/7240 .偶尔会这样做,并且可能会在整个 API 中更彻底地完成: https://github.com/jOOQ/jOOQ/issues/7240

It wouldn't help you, because you want to call .desc() on a column expression (the Select ), rather than wrap pass it to a method, so we're back at Java's limitation mentioned before.这对您没有帮助,因为您想在列表达式( Select )上调用.desc() ) ,而不是将其包装传递给方法,因此我们回到了前面提到的 Java 限制。

Kotlin and other languages Kotlin等语言

If you're using Kotlin or other languages that have some way of providing "extension functions", however, you could use this approach:但是,如果您使用 Kotlin 或其他具有某种方式提供“扩展功能”的语言,则可以使用以下方法:

inline fun <T> Select<Record1<T>>.desc(): SortField<T> {
    return DSL.field(this).desc();
}

jOOQ might provide these out of the box in the future: https://github.com/jOOQ/jOOQ/issues/6256 jOOQ 将来可能会提供这些开箱即用的功能: https://github.com/jOOQ/jOOQ/issues/6256

Turning the subquery into a Field works:将子查询转换为 Field 工作:

dsl.selectFrom(SERIES)
   .orderBy(DSL.field(dsl.select(DSL.max(COMPETITION.COMPETITION_DATE)).from(COMPETITION)
                  .where(COMPETITION.SERIES_ID.eq(SERIES.ID))).desc())
   .fetch()

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

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