Как получить набор результатов путем проверки определенного элемента в агрегированном массиве с помощью JOOQ?

#java #postgresql #jooq

#java #postgresql #jooq

Вопрос:

Я хочу отфильтровать результаты по определенному значению в агрегированном массиве в запросе.

Вот небольшое описание проблемы. Раздел принадлежит саду. Сад принадлежит округу, а округ принадлежит провинции. У пользователей есть несколько разделов. Эти разделы принадлежат их садам, и они относятся к их районам, а они — к провинции.

Я хочу получить идентификаторы пользователей, которые имеют значение 2 в массиве district. Я пытался использовать любой оператор, но он не работает должным образом. (синтаксическая ошибка) Будем признательны за любую помощь.

ps: Это возможно при написании с использованием обычного SQL

 rs = dslContext.select(
                        field("user_id"),
                        field("gardens_array"),
                        field("province_array"),
                        field("district_array"))
                .from(table(select(
                        arrayAggDistinct(field("garden")).as("gardens_array"),
                        arrayAggDistinct(field("province")).as("province_array"),
                        arrayAggDistinct(field("distict")).as("district_array"))
                                .from(table("lst.user"))
                                .leftJoin(table(select(
                                        field("section.user_id").as("user_id"),
                                        field("garden.garden").as("garden"),
                                        field("garden.province").as("province"),
                                        field("garden.distict").as("distict"))
                                        .from(table("lst.section"))
                                        .leftJoin("lst.garden")
                                        .on(field("section.garden").eq(field("garden.garden")))
                                        .leftJoin("lst.district")
                                        .on(field("district.district").eq(field("garden.district")))).as("lo"))
                                .on(field("user.user_id").eq(field("lo.user_id")))
                                .groupBy(field("user.user_id"))).as("joined_table"))
                .where(val(2).equal(DSL.any("district_array"))
                .fetch()
                .intoResultSet();
  

Комментарии:

1. Нет причин для того, чтобы этот вопрос получил 3 отрицательных отзыва. Насколько я могу судить, это совершенно законно…

Ответ №1:

Вызывается ваш код DSL.any(T...) , который соответствует выражению any(?) в PostgreSQL, где значением привязки в вашем случае является String[] . Но вы не хотите, чтобы "district_array" было значением привязки, вы хотите, чтобы это была ссылка на столбец. Итак, либо вы присваиваете свое arrayAggDistinct() выражение локальной переменной и повторно используете его, либо вы повторно используете свое field("district_array") выражение или реплицируете его:

 val(2).equal(DSL.any(field("district_array", Integer[].class)))
  

Обратите внимание, что обычно хорошей идеей является четкое указание типов данных (например, Integer[].class ) при работе с простым SQL templating API или, что еще лучше, использовать генератор кода.

Комментарии:

1. Не удается разрешить метод ‘equal(org.jooq. QuantifiedSelect<org.jooq. Record1<T>>) Это точная ошибка, которую я получаю. Спасибо за предложения.

2. не могли бы вы, пожалуйста, проверить синтаксис?

3. @AshanTharindu, я допустил ошибку, это должно быть Integer[] из-за того, что вы используете arrayAgg() , но что касается ошибок компиляции, это не должно иметь значения