Comprendí que desea sumar un valor y un valor b para cada fila y luego ordenar cada fila por valor de suma. ¿verdad?
-> ->>
Esta es la forma de seleccionar la clave o el valor en formato JSON en PostgreSQL (no sé si también funciona en MySQL u otros, normalmente trabajé con PostgreSQL). Hay un buen recurso en aquí
. sus datos en una columna llamada 'data
' es {"aa":3, "bb":2, "cc":5}
. entonces selecciona un valor aa por data->>'aa'
. ¿Qué sucede si {'classification':{'pc':5000}}
? debe seleccionar el valor de pc. Entonces data->'classification'->>'pc'
::la notación es una operación de conversión.
CAST(data->'aa' AS INTEGER)
data->'aa'::int
clase RawSQL(sql, params, campo_de_salida=Ninguno)
RawSQL("((data->>'aa'::int), (0,)") no significa que si aa no existe, tiene valor 0. 0 es params.
queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))
Bueno, si puedes modificar tus datos así
- id:1, datos ={'aa':1, 'bb':2, 'cc':4}
- id:2, datos ={'aa':3, 'bb':2, 'cc':0}
- id:3, datos ={'cc':7, 'bb':0, 'cc':0}
- id:4, datos ={'bb':7, 'bb':0, 'cc':0}
Esto puede funcionar.
Contract.objects.annotate(
sumVal=RawSQL("((data->>'aa')::int)", (0,))+RawSQL("((data->>'cc')::int)",(0,)))
.order_by('sumVal')
Sugerí usar Coalesce. el autor de esta pregunta se dio cuenta. Hay un código debajo.
raw_sql = "+".join(["COALESCE((data->>%s)::int, 0)" for _ in ['aa', 'cc'])
MyMoodel.objects.all()
.annotate(my_sum=RawSQL(raw_sql, params=('aa', 'cc')))
.order_by('my_sum')