PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

django - agréger les clés spécifiques au champ json et les classer par agrégation

J'ai compris que vous vouliez résumer une valeur et une valeur b pour chaque ligne, puis ordonner chaque ligne par valeur somme. n'est-ce pas ?

-> ->> Voici comment sélectionner une clé ou une valeur au format JSON dans PostgreSQL (je ne sais pas si cela fonctionne également dans MySQL ou d'autres, je travaillais normalement avec PostgreSQL). Il y a une bonne ressource dans ici . vos données dans une colonne nommée 'data ' est {"aa":3, "bb":2, "cc":5} . donc vous sélectionnez une valeur par data->>'aa' . Et si {'classification':{'pc':5000}} ? vous devez sélectionner la valeur pc. Puis data->'classification'->>'pc'

::la notation est une opération de transtypage.

CAST(data->'aa' AS INTEGER)

data->'aa'::int

classe RawSQL(sql, params, output_field=None)

RawSQL("((data->>'aa'::int), (0,)") ne signifie pas que si aa n'existe pas, il a la valeur 0. 0 est params.

queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

Eh bien, si vous pouvez modifier vos données comme ceci

  • 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}

Cela peut fonctionner.

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

J'ai suggéré d'utiliser Coalesce. l'auteur de cette question compris. Il y a du code ci-dessous.

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