PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

django - agrega chaves específicas do campo json e ordena pela agregação


Eu entendi que você deseja somar um valor e um valor b para cada linha e, em seguida, ordenar cada linha por valor de soma. certo?

-> ->> Isto é como selecionar chave ou valor no formato JSON no PostgreSQL (não sei se também funciona no MySQL ou em outros, normalmente trabalhava com o PostgreSQL). Existe um bom recurso em aqui . seus dados em uma coluna chamada 'data ' é {"aa":3, "bb":2, "cc":5} . então você seleciona um valor aa por data->>'aa' . E se {'classification':{'pc':5000}} ? você precisa selecionar o valor do pc. Então data->'classification'->>'pc'

::notação é operação de conversão.
CAST(data->'aa' AS INTEGER)

data->'aa'::int

class RawSQL(sql, params, output_field=Nenhum)

RawSQL("((data->>'aa'::int), (0,)") não significa que se aa não existe, tem valor 0. 0 é params.
queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

Bem, se você pode modificar seus dados assim
  • id:1, data ={'aa':1, 'bb':2, 'cc':4}
  • id:2, data ={'aa':3, 'bb':2, 'cc':0}
  • id:3, data ={'cc':7, 'bb':0, 'cc':0}
  • id:4, data ={'bb':7, 'bb':0, 'cc':0}

Isso pode funcionar.
Contract.objects.annotate(
sumVal=RawSQL("((data->>'aa')::int)", (0,))+RawSQL("((data->>'cc')::int)",(0,)))
.order_by('sumVal')

Eu sugeri usar Coalesce. o autor desta pergunta descobriu. Há um código abaixo.

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