Кассандра Десятичные вопросы точности - PullRequest
2 голосов
/ 19 сентября 2019

Я хранил некоторую валюту в Кассандре как десятичные типы, и я обнаружил, что они не выходят так точно, как введено.Обычно это нормально, но иногда мне нужна точность (2 десятичных знака).Я попытался добавить точный синтаксис ко всему моему коду (создать таблицу, выбрать, вставить), и все это не с синтаксическими ошибками.Мне кажется, что более эффективно выполнять округление при обращении к базе данных, а не в Pandas DataFrame, поэтому я проверяю, есть ли у кого-нибудь решение.Я пробую синтаксисы в cqlsh и Python.

cqlsh 5.0.1 |Кассандра 3.11.2 |CQL spec 3.4.4 |Собственный протокол v4

Попытка сделать это для столбца таблицы:

CREATE TABLE IF NOT EXISTS myTable (
    myid text,
    price decimal(14,2),
    PRIMARY KEY(id)
);

cassandra.protocol.SyntaxException: <Error from server: code=2000 [Syntax error in CQL query] message="line XXXXX no viable alternative at input '(' (... [decimal](...):>

Я увидел комментарий, что Кассандра не допускает точности в определениях таблиц, так что хорошо, двигаясь дальше.

Попытка сделать это при SELECT:

SELECT myid, cast(price as Decimal(14,2)) FROM myTable;

Syntax Exception: mismatched input '(' expecting ')' (...myid, cast(price as Decimal[(]...)

Я пропущу вставку, потому что ошибки избыточны, а также значения в DataFrame имеют правильную точность при вводе.Хранение и выбор таблицы - это то место, где она становится неуклюжей.

Ошибка SELECT, потому что невозможно преобразовать десятичное число в десятичное: http://cassandra.apache.org/doc/latest/cql/functions.html

Если я не могу указать точность в таблицесемантику, и я не могу сохранить ее как десятичную и привести ее с правильной точностью, я полагаю, что я вынужден:

  • сохранить в double и привести к выбору, ИЛИ
  • программноокруглить мой DataFrame после его возвращения?

Редактировать:

Для полноты картины это одно решение, которое работает, хотя я бы предпочел наиболее эффективное решениеЯ думаю, что это будет округление на уровне выборки данных.В любом CQL нет модификаторов точности, использующих десятичный тип для столбца цены.Решение адаптировано из ( Десятичное округление классов в Pandas ), так как df.round () не работает с Десятичным Python.

<set pandas row factory>
df = dbConnection.execute('SELECT myid, price FROM myTable')._current_rows
df[['price']] = df[['price']].applymap(lambda x: x.quantize(decimal.Decimal('.01')))

1 Ответ

2 голосов
/ 19 сентября 2019

CQL в отличие от баз данных SQL не позволяет настраивать десятичную точность и т. Д., Поэтому вам просто нужно использовать decimal.Данные, которые вы получаете обратно в cqlsh, форматируются самим cqlsh - в конфигурации по умолчанию он просто вызывает str на экземпляре типа Python Decimal (см. код ).Он может вызвать другой модуль форматирования, если для десятичного разделителя установлено значение, отличное от ., или если установлен разделитель тысяч.

Но я бы посоветовал не полагаться на реализацию cqlsh и использовать драйвер напрямую,и отформатируйте полученное значение decimal как хотите.

...