Проблема округления при делении значения COUNT на другое значение с помощью jooq

При использовании SQL я могу выполнить простой запрос, такой как запрос ниже, без проблем, он возвращает ответ с 4 десятичными знаками:

SELECT(COUNT(ID)/7) FROM myTable;

Если приведенное выше значение возвращает значение 12, возвращаемое значение выбора в рабочей среде составляет 1,7143.

Моя проблема возникает, когда я использую jooq, чтобы сделать этот расчет:

dsl.select(count(MYTABLE.ID).divide(7).from(MYTABLE).fetch();

Приведенный выше код возвращает мне значение 1, а я хочу значение 1.7143.

У меня есть подобные строки кода Jooq, которые используют SUM, а не COUNT, и они возвращают значение до 4 десятичных знаков, но я не могу найти способ получить вышеуказанный код, чтобы вернуть значение до 4 десятичных знаков.

Я пытался использовать .round но не имели успеха.

Кто-нибудь еще сталкивался с подобной проблемой и знает решение?

1 ответ

Решение

Здесь есть две проблемы, в зависимости от того, какую СУБД вы используете:

1. Тип всего проецируемого выражения

Тип целого выражения деления зависит от типа левой части (дивиденд), который SQLDataType.INTEGER, Таким образом, независимо от того, возвращает ли ваша СУБД десятичное число или число с плавающей запятой, jOOQ будет использовать JDBC ResultSet.getInt() метод для получения значения, где вы будете терять точность. Итак, первый шаг - убедиться, что jOOQ выберет нужный тип данных. Есть несколько способов сделать это:

  1. Используйте актерский состав на COUNT(*) выражение: count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7)
  2. Используйте приведение ко всему выражению: count(MYTABLE.ID).divide(7).cast(SQLDataType.DOUBLE)
  3. Используйте приведение типа данных в любом выражении: expr.coerce(SQLDataType.DOUBLE)

Приведения влияют на сгенерированный SQL. Приведения типа данных нет.

2. Как ваша СУБД обрабатывает типы данных

В большинстве RDBMS, count(*) выражения производят целочисленный тип, и правая часть вашего деления (делитель) также является целым числом, поэтому наилучшим полученным типом данных является, по сути, целочисленный тип. Я подозреваю, что вы должны пройти double или же BigDecimal введите вместо этого ваш делитель.

Решение

Идеальным решением было бы объединить два вышеупомянутых:

dsl.select(count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7.0))
   .from(MYTABLE)
   .fetch();
Другие вопросы по тегам