2017-09-19 2 views
1

postgres 데이터베이스에서 sqlalchemy를 사용하고 있는데 float를 나타내는 두 개의 JSON 필드에서 SELECT의 산술 연산을 수행하려고합니다. 그러나, 나는이 일을하는 방법을 알아 내지 못했습니다. JSON 필드에서 sqlalchemy/postgres : 산술?

내가 제대로 테이블이 cost_data라는 JSON 열을 포함 transactions라고 정의 가정하고,이 JSON 구조가 cost 및 부동 소수점 값을 나타냅니다 subtotal라는 두 개의 속성이 포함되어 있다고 가정합니다.

(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 설정받을 경우 다음과 같이

SELECT 성명에서, 나는 그 두 개의 필드의 합계를 생성 각각 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... 
               ^

분명히 이것은 필드가 문자열로 제공되고 "+"연산자가 문자열 연결로 해석되기 때문입니다. 이온. 내가 파이썬 float 연산자를 사용하는 경우

또한, 그것은 또한

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

파이썬 인터프리터도 코드를 실행하지 않습니다 ... 실패하고이 오류 제공합니다

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

그러면 sqlalchemy를 사용하여이 두 필드를 어떻게 추가 할 수 있습니까?

PS : 다음은 ... OK

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

참고 그 돈을 가지고 부동 소수점하는 것은 나쁜 일치 될 수 있습니다. [대신 숫자를 사용할 수 있습니다.] (https://stackoverflow.com/questions/45689496/query-a-specific-json-column-postgres-with-sqlalchemy). –

+0

일반적으로 동의합니다. 이 경우 데이터베이스 열 정의를 변경할 수 없으며 다른 소프트웨어는이 필드에 대해 float를 사용합니다. – HippoMan

답변

0

전형적인 cost_data 열 값이다. 나는 마침내 그것을 알아 냈다. 나는 다음과 같이 ... cast을 적용하기 전에 astext 연산자를 통해 각 기준을 통과

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