Проблема округления при делении значения 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 выберет нужный тип данных. Есть несколько способов сделать это:
- Используйте актерский состав на
COUNT(*)
выражение:count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7)
- Используйте приведение ко всему выражению:
count(MYTABLE.ID).divide(7).cast(SQLDataType.DOUBLE)
- Используйте приведение типа данных в любом выражении:
expr.coerce(SQLDataType.DOUBLE)
Приведения влияют на сгенерированный SQL. Приведения типа данных нет.
2. Как ваша СУБД обрабатывает типы данных
В большинстве RDBMS, count(*)
выражения производят целочисленный тип, и правая часть вашего деления (делитель) также является целым числом, поэтому наилучшим полученным типом данных является, по сути, целочисленный тип. Я подозреваю, что вы должны пройти double
или же BigDecimal
введите вместо этого ваш делитель.
Решение
Идеальным решением было бы объединить два вышеупомянутых:
dsl.select(count(MYTABLE.ID).cast(SQLDataType.DOUBLE).divide(7.0))
.from(MYTABLE)
.fetch();