2017-09-19 30 views
1

我在postgres数据库上使用sqlalchemy,我试图在两个表示浮点数的JSON字段的SELECT中进行算术运算。但是,我还没有想出如何使这项工作。sqlalchemy/postgres:JSON字段上的算术?

假设我已经正确定义的表中调用transactions,内含cost_data一个JSON柱,并假定此JSON结构包含两个属性称为costsubtotal代表的浮点值。

SELECT声明,我产生这两个字段的总和如下:

(cast(transactions.c.cost_data['subtotal'], sqlalchemy.Float) + cast(transactions.c.cost_data['cost'], sqlalchemy.Float)).label('total_cost') 

这将生成以下SQL片段...

CAST((transactions.cost_data -> %(cost_data_6)s) AS FLOAT) + CAST((transactions.cost_data -> %(cost_data_7)s) AS FLOAT) AS total_cost 

(其中cost_data_6cost_data_7被置分别为subtotalcost)。

不过,我得到以下错误:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) cannot cast type json to double precision 

如果我删除了铸造和做如下,它也失败...

(transactions.c.cost_data['subtotal'] + transactions.c.cost_data['cost']).label('total_cost') 

我得到这个错误...

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) operator does not exist: json || json 
LINE 9: ... (transactions.cost_data -> 'subtotal') || (transa... 
               ^

显然,这是因为字段以字符串形式出现,“+”运算符被解释为字符串concatenat离子。

另外,如果我使用Python float运营商,它也失败...

(float(transactions.c.cost_data['subtotal']) + float(transactions.c.cost_data['cost'])).label('total_cost') 

Python解释器甚至不执行的代码,它给这个错误:

TypeError: float() argument must be a string or a number, not 'BinaryExpression' 

那么如何使用sqlalchemy执行这两个字段的添加?

PS:下面是一个典型的cost_data列值...

{"cost":3.99,"subtotal":12.34} 
+0

注意,金钱和浮点可能是一个糟糕的比赛。 [你可以用数字代替](https://stackoverflow.com/questions/45689496/query-a-specific-json-column-postgres-with-sqlalchemy)。 –

+0

一致同意。在这种情况下,我无法更改数据库列定义,而其他软件使用这些字段的浮点数。 – HippoMan

回答

0

确定。我终于弄明白了。我已经申请cast之前穿过astext运营商每个参考,如下...

(transactions.c.cost_data['subtotal'].astext.cast(sqlalchemy.Float) + transactions.c.cost_data['cost'].astext.cast(sqlalchemy.Float)).label('total_cost')