简体   繁体   English

在 JOOQ 的 select 中使用 UNNEST

[英]Use UNNEST inside JOOQ's select

I have the SQL like:我有 SQL 之类的:

select *
from some_table
where (select array(select unnest(first_array_field) except select unnest(second_array_field))) @> '{some_value}';

This is my try to write the where condition for that query in a JOOQ way:这是我尝试以 JOOQ 方式编写该查询的where条件:

  private Condition selectAwayValue(
      List<Long> list) {

    var allSelect = dslContext
        .select(TABLE.ARRAY_1)
        .from(DSL.unnest(TABLE.ARRAY_1));

    var homeSelect = dslContext
        .select(TABLE.ARRAY_2)
        .from(DSL.unnest(TABLE.ARRAY_2));

    var awaySelect = allSelect.except(homeSelect);

    var awayArray = dslContext.select(DSL.array(awaySelect));

    return awayArray.asField().contains(awayCompetitorIdsList);
  }

I'm facing 2 problems here:我在这里面临两个问题:

  1. I got the different SQL than I expected (see above)我得到的 SQL 与我预期的不同(见上文)
  2. Also got the exception like Cannot convert from 5 (class java.lang.Long) to class [Ljava.lang.Long;也得到了异常,例如Cannot convert from 5 (class java.lang.Long) to class [Ljava.lang.Long;

I understand what's the exceptions says to me, but don't understand why:)我明白例外对我说了什么,但不明白为什么:)

What's would be the best way to write my SQL in a jooq syntax?用 jooq 语法编写我的 SQL 的最佳方法是什么?

I'm using the latest stable jooq version, the latest stable Postgres version我正在使用最新的稳定 jooq 版本,最新的稳定 Postgres 版本

thanks谢谢

Alternative solution替代解决方案

If you think of your problem this way:如果你这样想你的问题:

select *
from some_table
where first_array_field @> '{some_value}'
and not second_array_field @> '{some_value}';

Then, the problem is a lot simpler to express in jOOQ as well然后,这个问题在 jOOQ 中也更容易表达

ctx.selectFrom(SOME_TABLE)
   .where(SOME_TABLE.FIRST_ARRAY_FIELD.contains(new Long[] { someValue }))
   .andNot(SOME_TABLE.SECOND_ARRAY_FIELD.contains(new Long[] { someValue }))
   .fetch();

Why your solution didn't work为什么您的解决方案不起作用

Of course, you could pull this off using your own approach.当然,您可以使用自己的方法完成此操作。 Regarding the problems you've observed:关于您观察到的问题:

I got the different SQL than I expected (see above)我得到的 SQL 与我预期的不同(见上文)

That syntax where you put UNNEST() in SELECT is not supported by jOOQ. jOOQ 不支持将UNNEST()放入SELECT的语法。 It is quite the weird syntax in PostgreSQL as well, and doesn't do what you might think it does in many ways. PostgreSQL 中的语法也很奇怪,并且在很多方面都没有做你认为它会做的事情。 Have you tried putting two instances of UNNEST() in SELECT ?您是否尝试在SELECT中放置两个UNNEST()实例? The second one won't form a cartesian product like the first one.第二个不会像第一个那样形成笛卡尔积。 Rows from it will be matched with the first one's rows by ordinality.它的行将按序数与第一个行匹配。

However, using UNNEST in FROM is correct and also more intuitive in native PostgreSQL, even if it's a bit longer.但是,在FROM中使用UNNEST是正确的,并且在本机 PostgreSQL 中也更直观,即使它有点长。 And it's supported by jOOQ.它得到了 jOOQ 的支持。

Also got the exception like Cannot convert from 5 (class java.lang.Long) to class [Ljava.lang.Long;也得到了异常,例如无法从 5(类 java.lang.Long)转换为 class [Ljava.lang.Long;

This is because you seem to be calling Field.contains() with a scalar argument, instead of an array.这是因为您似乎使用标量参数而不是数组调用Field.contains() See the example from the Javadoc, or my example above:请参阅 Javadoc 中的示例或我上面的示例:

 // Use this expression
 val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })

 // ... to render this SQL
 ARRAY[1, 2, 3] @> ARRAY[1, 2]

But again, I think my alternative approach is much simpler.但同样,我认为我的替代方法要简单得多。

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

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