2017-09-19 25 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')