I have some finance numbers (as in 1234567891234567891234.1234567891234567) where I need to have full precision, and I cannot find how to achieve this on QuestDB, as both float and double would not be suitable.
At the proposal of a core engineer at QuestDB slack I am storing now the integer part and decimal part as two different long numbers. But I cannot figure out how to use them for aggregations.
CREATE TABLE test_sum (
name SYMBOL,
ts timestamp,
price_integer_part long,
price_decimal_part long
) TIMESTAMP(ts) PARTITION BY DAY WAL;
-- 10000.9998 + 10000.9998 = 20001.9996
INSERT INTO test_sum VALUES ('btc', '2023-07-14', '10000','9998');
INSERT INTO test_sum VALUES ('btc', '2023-07-14', '10000','9998');
I have some finance numbers (as in 1234567891234567891234.1234567891234567) where I need to have full precision, and I cannot find how to achieve this on QuestDB, as both float and double would not be suitable.
At the proposal of a core engineer at QuestDB slack I am storing now the integer part and decimal part as two different long numbers. But I cannot figure out how to use them for aggregations.
CREATE TABLE test_sum (
name SYMBOL,
ts timestamp,
price_integer_part long,
price_decimal_part long
) TIMESTAMP(ts) PARTITION BY DAY WAL;
-- 10000.9998 + 10000.9998 = 20001.9996
INSERT INTO test_sum VALUES ('btc', '2023-07-14', '10000','9998');
INSERT INTO test_sum VALUES ('btc', '2023-07-14', '10000','9998');
Share
Improve this question
edited yesterday
Javier Ramirez
asked 2 days ago
Javier RamirezJavier Ramirez
4,0081 gold badge27 silver badges36 bronze badges
6
|
Show 1 more comment
1 Answer
Reset to default 0After some fiddling, this works, but you need to know the number of decimal places. The result of the operation is in the last column, but I am leaving the rest of the columns just to see what we are calculating step by step.
SELECT
name,
SUM(price_integer_part) + SUM(price_decimal_part) / 10000 AS total_price,
FLOOR(SUM(price_decimal_part) / 10000) AS carry,
SUM(price_decimal_part) % 10000 / 10000 AS new_decimal,
SUM(price_decimal_part) % 10000::double / 10000 AS new_decimal_fraction,
(SUM(price_integer_part) + SUM(price_decimal_part) / 10000) + (SUM(price_decimal_part) % 10000::double / 10000) as result
FROM test_sum;
It gives the exact result of 20001.9996
.
The values of the intermediate columns are: total_price:20001
, carry:1
, new_decimal:0
, new_decimal_fraction:0.9996
long
. You will store mills and have to divide by 1000 everytime you want to get to the base currency. – Thorsten Kettner Commented 2 days ago