sql >> Base de Datos >  >> RDS >> PostgreSQL

django:agrega claves específicas de campo json y ordena por agregación

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')