Например:
SELECT S1__AMOUNT * S1__PRICE * S1__UNITS * 1000
Все столбцы, такие как S1__AMOUNT, S1__PRICE и т. д., имеют формат DECIMAL(38,10).
При умножении нескольких таких столбцов (особенно трех или более) и затем умножении на константу (например, * 1000) я получаю:
duckdb.duckdb.OutOfRangeException: Out of Range Error:
Overflow in multiplication of DECIMAL(38) (194586756000000000000000000000000000 * 1000).
You might want to add an explicit cast to a decimal with a smaller scale.
Ограничения:
Я не могу выполнить приведение к DOUBLE, но после каждой операции разрешено приводить ее результат к десятичному виду (38,10)
Я знаю, что могу вручную переписать предложения SQL для приведения после каждого шага, например:
CAST(
CAST(
CAST(S1__AMOUNT * S1__PRICE AS DECIMAL(38,10))
* S1__UNITS AS DECIMAL(38,10)
)
* 1000 AS DECIMAL(38,10)
)
Но поскольку предложения SQL пишутся клиентом и могут быть довольно случайными, я не хочу использовать этот неуклюжий и подверженный ошибкам способ.
Вопрос:
Есть ли какой-нибудь способ настроить DuckDB так, чтобы он:
- Автоматически уменьшал промежуточный десятичный масштаб/точность, если необходимо вписаться внутрь DECIMAL(38,10), без создания исключения OutOfRangeException, или
- Автоматически приводит промежуточные арифметические результаты обратно к безопасному DECIMAL(38,10), или
- Предоставляет выражение/функцию для безопасного умножения с безопасным от переполнения десятичным продвижением?
Точный код для воспроизведения проблемы:
import duckdb
import polars as pl
df = pl.DataFrame({"AMOUNT": 8760, "PRICE": 22.2131, "RATE": 1})
df = df.cast(pl.Decimal(scale=10))
result = duckdb.sql("""
FROM df
SELECT AMOUNT * PRICE * RATE * 1000
""").pl()
print(result)
Подробнее здесь: https://stackoverflow.com/questions/798 ... g-decimals
Мобильная версия